Skip to content

/desktop-multiwindow-tauri

Tauri 2.x multi-window creation, event system, window state persistence, parent/child and modal windows

shell
$ npx -y skills add agents-inc/skills --skill desktop-multiwindow-tauri --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/desktop-multiwindow-tauri
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

Tauri 2.x multi-window creation, event system, window state persistence, parent/child and modal windows

SKILL.md

desktop-multiwindow-tauri.SKILL.md
name: desktop-multiwindow-tauri
description: Tauri 2.x multi-window creation, event system, window state persistence, parent/child and modal windows

Tauri Multi-Window & Events

> **Quick Guide:** Create windows from JS with `new WebviewWindow(label, options)` or from Rust with `WebviewWindowBuilder`. Communicate across windows using events: `emit()` broadcasts globally, `emitTo(label, event, payload)` targets a specific window, `emit_filter()` targets multiple windows by predicate. Always call the unlisten function returned by `listen()`. Use `tauri-plugin-window-state` to persist window position/size across sessions. Window labels must be unique and are used for both event targeting and permission scoping. > > **Current version:** Tauri 2.x (stable). Multi-webview in a single window requires the `unstable` feature flag.

---

<critical_requirements>

CRITICAL: Before Using This Skill

> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)

**(You MUST give every window a unique label -- labels identify windows for event targeting, permissions, and retrieval)**

**(You MUST always call the unlisten function returned by `listen()` / `once()` -- leaked listeners cause memory leaks in long-running apps)**

**(You MUST check if a window already exists before creating it -- duplicate labels cause runtime errors)**

**(You MUST add window labels to capability file `windows` array -- windows without permissions cannot use plugins or core APIs)**

**(You MUST use `@tauri-apps/api/event` for global events and `@tauri-apps/api/webviewWindow` for window-scoped events -- mixing them causes missed events)**

</critical_requirements>

---

**Auto-detection:** WebviewWindow, WebviewWindowBuilder, emit_to, emitTo, emit_filter, EventTarget, window label, multi-window, onCloseRequested, tauri-plugin-window-state, parent window, modal window, WebviewBuilder, add_child, getCurrentWebviewWindow, window.listen, window.emit, cross-window communication

**When to use:**

  • Creating secondary windows (settings, preferences, about, detached panels)
  • Communicating between windows via the Tauri event system
  • Handling window close confirmation (unsaved changes dialogs)
  • Persisting window size/position across app restarts
  • Setting up parent/child or modal window relationships
  • Building multi-panel layouts with multiple webviews in a single window

**When NOT to use:**

  • Single-window apps with no inter-window communication (use the base Tauri framework skill)
  • General Tauri commands, IPC, or plugin setup (use the base Tauri framework skill)
  • Frontend framework state management within a single window (use respective framework skills)

**Key patterns covered:**

  • Window creation from JS and Rust ([examples/core.md](examples/core.md))
  • Event system: emit, emitTo, emit_filter for targeted messaging ([examples/core.md](examples/core.md))
  • Cross-window state synchronization via events ([examples/core.md](examples/core.md))
  • Window close confirmation with onCloseRequested ([examples/core.md](examples/core.md))
  • Window state persistence with tauri-plugin-window-state ([examples/persistence.md](examples/persistence.md))
  • Parent/child windows and modal dialogs ([examples/advanced.md](examples/advanced.md))
  • Multi-webview in a single window (unstable) ([examples/advanced.md](examples/advanced.md))

**Detailed resources:**

  • [examples/core.md](examples/core.md) - Window creation, event system, close confirmation, cross-window sync
  • [examples/persistence.md](examples/persistence.md) - Window state plugin setup, manual save/restore, StateFlags
  • [examples/advanced.md](examples/advanced.md) - Parent/child windows, modals, multi-webview layouts
  • [reference.md](reference.md) - API quick reference, event method comparison, decision framework

---

<philosophy>

Philosophy

Tauri's multi-window architecture is built on two key concepts: **window labels** for identification and **events** for communication.

Every window has a unique string label assigned at creation. This label is used everywhere: event targeting with `emitTo`, permission scoping in capability files, and retrieval with `app.get_webview_window(label)`. Labels are the window's address.

The event system follows a pub-sub model with three tiers of targeting:

1. **Global** (`emit`) -- all listeners in all windows receive the event 2. **Targeted** (`emitTo`) -- only listeners in the specified window receive the event 3. **Filtered** (`emit_filter`) -- listeners matching a predicate receive the event

**When to use multi-window patterns:**

  • App needs separate UI surfaces (settings panel, file viewer, log output)
  • Need to decouple UI concerns into independent windows
  • Need modal dialogs that block interaction with the parent window
  • Need persistent panel layouts (IDE-style split views)

**When NOT to use multi-window:**

  • A tabbed interface within a single window handles the use case
  • The secondary UI is a simple overlay/modal that lives in the same DOM
  • You only need to show/hide sections of a single-page app

</philosophy>

---

<patterns>

Core Patterns

Pattern 1: Window Creation

Create windows from JavaScript or Rust. Always check if the window exists first to avoid duplicate-label errors.

import { WebviewWindow } from "@tauri-apps/api/webviewWindow";

const SETTINGS_WINDOW_LABEL = "settings";
const SETTINGS_WIDTH = 600;
const SETTINGS_HEIGHT = 400;

// Check if already open, focus it instead of creating duplicate
const existing = await WebviewWindow.getByLabel(SETTINGS_WINDOW_LABEL);
if (existing) {
  await existing.setFocus();
  return;
}

const settingsWindow = new WebviewWindow(SETTINGS_WINDOW_LABEL, {
  url: "settings.html",
  title: "Settings",
  width: SETTINGS_WIDTH,
  height: SETTINGS_HEIGHT,
  resizable: false,
  center: true,
});

settingsWindow.once("tauri://created", () => {
  console.log("Settings window creat
Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withagents-inc-skills

The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Get the whole plugin, auto-invoked