Tauri 2 has been out since October 2024, but much of what agents learnt is Tauri 1. Tauri 2 moved invoke to @tauri-apps/api/core, replaced appWindow, split fs, dialog, shell and http into plugins, replaced the allowlist with capabilities, renamed tauri.conf.json keys (tauri to app, distDir to frontendDist, devPath to devUrl) and renamed core Rust APIs (get_window, emit_all, SystemTray, WindowBuilder). It also expects command arguments in camelCase from JavaScript, which catches out new Tauri 2 code too.
This loadout pairs a Cursor rule and AGENTS.md (a never/always table covering the front end, the config and Rust) with a skill that checks the work. A standard-library Python scanner reports Tauri 1 code as errors across .ts/.js, .rs, tauri.conf.json, Cargo.toml and package.json. Then tsc checks the front end, a Node test mocks the IPC to pin the argument names, and the config is validated against the schema shipped in the Tauri CLI. The verifier runs all of this on a Tauri 2 notes app and a Tauri 1 sample, and checks the Rust names against the published tauri 2.12.5 crate source. For least-privilege capabilities, pair it with the Tauri 2 desktop app loadout.
What's in it
- Never/always table for the front end, tauri.conf.json and Rust
- Scanner flags Tauri 1 imports, config keys and Rust APIs as errors
- Warns on snake_case invoke arguments, which Tauri 2 doesn't map
- A Node test with @tauri-apps/api/mocks pins the camelCase argument names
- Validates tauri.conf.json against the schema shipped in the Tauri CLI
You'll need
- Tools:
node,python3
Verification
| Check | Result | What we found |
|---|---|---|
| Listinglisting.yaml matches the schema and declares every file in the folder. | Pass | Schema valid; 11 files declared, none missing or extra
|
| Files parseJSON parses; SKILL.md and .mdc front matter is valid YAML with the fields each agent needs; code fences are closed. | Pass | All 11 files parse; front matter valid |
| AdaptersCLAUDE.md imports @AGENTS.md, GEMINI.md imports @./AGENTS.md, and both match the generator. | Pass | CLAUDE.md and GEMINI.md import AGENTS.md and are up to date
|
| Install pathsEvery file lands where each agent documents it, with no collisions, and the laid-out project is re-discovered correctly. | Pass | Correct paths for all 6 agents; layouts re-discovered
|
| MCP configmcp.json is structurally valid, converts to each agent's format, declares no literal secrets, and referenced packages exist on npm/PyPI. | Not applicable | No MCP servers in this loadout |
| Safety scanThe intake scanner finds no credentials, risky shell, hidden Unicode, instructions hidden in HTML comments or after long blank padding, or prompt-injection and covert wording (such as telling the agent to keep something from you), and the listing's network flag is honest. | Pass | Clean: no credentials, risky shell, hidden text or covert instructions
|
| ReferencesLinks and file paths between the loadout's files resolve, including for each agent's installed layout. | Pass | 3 references between files resolve for every agent |
| Size limitsFile count and sizes are within the submission limits; SKILL.md bodies stay under 500 lines. | Pass | 11 files, 22.6 KB total; largest skills/tauri-2-guard/scripts/tauri2_guard.py 8.4 KB
|
| LicenceA recognised SPDX licence, with the licence text available. | Pass | MIT, by SetupBay; text in the repository LICENSE |
| Starter buildA minimal fixture project with the loadout applied installs and builds or type-checks, and the loadout's own code examples compile. | Pass | tauri2_guard.py passes a Tauri 2 notes app (front end, lib.rs, main.rs, tauri.conf.json, Cargo.toml) and flags every Tauri 1 line in the skill's four sample files: 25 errors and 3 warnings, including the snake_case invoke argument. With the pinned @tauri-apps packages, tsc passes the front end, a no
|
What this means: a script checked the files themselves: they parse, they install where each agent looks, any MCP config is sound, the safety scan is clean, references between files resolve, and, where a free and repeatable fixture exists, a small starter project builds with the loadout applied. No AI agent was run. Per-agent results from agent runs are separate and stay untested until an agent actually runs.
Install
Choose your agent. Run the commands from your project root, or download a zip already laid out in the right folders.
Claude Code reads CLAUDE.md (imports AGENTS.md with @AGENTS.md) and skills from .claude/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/AGENTS.md curl -fsSL --create-dirs -o CLAUDE.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/CLAUDE.md curl -fsSL --create-dirs -o .claude/skills/tauri-2-guard/SKILL.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/SKILL.md curl -fsSL --create-dirs -o .claude/skills/tauri-2-guard/scripts/tauri2_guard.py https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/scripts/tauri2_guard.py curl -fsSL --create-dirs -o .claude/skills/tauri-2-guard/references/v1-to-v2.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/v1-to-v2.md curl -fsSL --create-dirs -o .claude/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt curl -fsSL --create-dirs -o .claude/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt curl -fsSL --create-dirs -o .claude/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt curl -fsSL --create-dirs -o .claude/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
CLAUDE.md | CLAUDE.md |
skills/tauri-2-guard/SKILL.md | .claude/skills/tauri-2-guard/SKILL.md |
skills/tauri-2-guard/scripts/tauri2_guard.py | .claude/skills/tauri-2-guard/scripts/tauri2_guard.py |
skills/tauri-2-guard/references/v1-to-v2.md | .claude/skills/tauri-2-guard/references/v1-to-v2.md |
skills/tauri-2-guard/references/tauri1-sample/main.ts.txt | .claude/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt |
skills/tauri-2-guard/references/tauri1-sample/main.rs.txt | .claude/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt |
skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt | .claude/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt |
skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt | .claude/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want. Which file wins when several are present: what Claude Code reads.
Codex CLI reads AGENTS.md and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/SKILL.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/SKILL.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/scripts/tauri2_guard.py https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/scripts/tauri2_guard.py curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/v1-to-v2.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/v1-to-v2.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/tauri-2-guard/SKILL.md | .agents/skills/tauri-2-guard/SKILL.md |
skills/tauri-2-guard/scripts/tauri2_guard.py | .agents/skills/tauri-2-guard/scripts/tauri2_guard.py |
skills/tauri-2-guard/references/v1-to-v2.md | .agents/skills/tauri-2-guard/references/v1-to-v2.md |
skills/tauri-2-guard/references/tauri1-sample/main.ts.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt |
skills/tauri-2-guard/references/tauri1-sample/main.rs.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt |
skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt |
skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want. Which file wins when several are present: what Codex CLI reads.
Cursor reads AGENTS.md + .cursor/rules/*.mdc and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .cursor/rules/tauri-2-only.mdc https://setupbay.com/raw/tauri-2-api-guard/1.0.0/.cursor/rules/tauri-2-only.mdc curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/SKILL.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/SKILL.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/scripts/tauri2_guard.py https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/scripts/tauri2_guard.py curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/v1-to-v2.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/v1-to-v2.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
.cursor/rules/tauri-2-only.mdc | .cursor/rules/tauri-2-only.mdc |
skills/tauri-2-guard/SKILL.md | .agents/skills/tauri-2-guard/SKILL.md |
skills/tauri-2-guard/scripts/tauri2_guard.py | .agents/skills/tauri-2-guard/scripts/tauri2_guard.py |
skills/tauri-2-guard/references/v1-to-v2.md | .agents/skills/tauri-2-guard/references/v1-to-v2.md |
skills/tauri-2-guard/references/tauri1-sample/main.ts.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt |
skills/tauri-2-guard/references/tauri1-sample/main.rs.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt |
skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt |
skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want. Which file wins when several are present: what Cursor reads.
Gemini CLI reads GEMINI.md (imports AGENTS.md with @./AGENTS.md) and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/AGENTS.md curl -fsSL --create-dirs -o GEMINI.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/GEMINI.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/SKILL.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/SKILL.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/scripts/tauri2_guard.py https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/scripts/tauri2_guard.py curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/v1-to-v2.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/v1-to-v2.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
GEMINI.md | GEMINI.md |
skills/tauri-2-guard/SKILL.md | .agents/skills/tauri-2-guard/SKILL.md |
skills/tauri-2-guard/scripts/tauri2_guard.py | .agents/skills/tauri-2-guard/scripts/tauri2_guard.py |
skills/tauri-2-guard/references/v1-to-v2.md | .agents/skills/tauri-2-guard/references/v1-to-v2.md |
skills/tauri-2-guard/references/tauri1-sample/main.ts.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt |
skills/tauri-2-guard/references/tauri1-sample/main.rs.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt |
skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt |
skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want. Which file wins when several are present: what Gemini CLI reads.
Antigravity CLI reads AGENTS.md (read natively; GEMINI.md is also read) and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/SKILL.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/SKILL.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/scripts/tauri2_guard.py https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/scripts/tauri2_guard.py curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/v1-to-v2.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/v1-to-v2.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/tauri-2-guard/SKILL.md | .agents/skills/tauri-2-guard/SKILL.md |
skills/tauri-2-guard/scripts/tauri2_guard.py | .agents/skills/tauri-2-guard/scripts/tauri2_guard.py |
skills/tauri-2-guard/references/v1-to-v2.md | .agents/skills/tauri-2-guard/references/v1-to-v2.md |
skills/tauri-2-guard/references/tauri1-sample/main.ts.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt |
skills/tauri-2-guard/references/tauri1-sample/main.rs.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt |
skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt |
skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want. Which file wins when several are present: what Antigravity CLI reads.
GitHub Copilot reads AGENTS.md and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/SKILL.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/SKILL.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/scripts/tauri2_guard.py https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/scripts/tauri2_guard.py curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/v1-to-v2.md https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/v1-to-v2.md curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt curl -fsSL --create-dirs -o .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt https://setupbay.com/raw/tauri-2-api-guard/1.0.0/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/tauri-2-guard/SKILL.md | .agents/skills/tauri-2-guard/SKILL.md |
skills/tauri-2-guard/scripts/tauri2_guard.py | .agents/skills/tauri-2-guard/scripts/tauri2_guard.py |
skills/tauri-2-guard/references/v1-to-v2.md | .agents/skills/tauri-2-guard/references/v1-to-v2.md |
skills/tauri-2-guard/references/tauri1-sample/main.ts.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt |
skills/tauri-2-guard/references/tauri1-sample/main.rs.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt |
skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt |
skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt | .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want. Which file wins when several are present: what GitHub Copilot reads.
Or as a Claude Code plugin
Adds the skill to Claude Code for all your projects, without copying files. Plugins can't carry project rules, so add AGENTS.md and CLAUDE.md with the commands above. About the plugin marketplace.
/plugin marketplace add https://setupbay.com/marketplace.json /plugin install tauri-2-api-guard@setupbay
Files
Rules AGENTS.md Tauri 2 version facts, rules and the done checklist. 40 lines
# AGENTS.md: Tauri 2 app (Tauri 1 API guard)
This desktop app runs **Tauri 2** (`tauri` crate 2.12, `@tauri-apps/api` 2.12). Tauri 2 came out in October 2024,
but much of what you learnt is Tauri 1: `@tauri-apps/api/tauri`, `appWindow`, `@tauri-apps/api/fs`, the
`allowlist`, `get_window`, `emit_all` and `SystemTray`. None of those work in Tauri 2.
## Version facts
- Check the pins first: `src-tauri/Cargo.toml` (`tauri = "2..."`) and `package.json` (`@tauri-apps/api` 2.x).
If either says 1.x, stop and ask; don't mix the two.
- Front end: `invoke` comes from `@tauri-apps/api/core`. The current window is `getCurrentWebviewWindow()` from
`@tauri-apps/api/webviewWindow`. fs, dialog, shell, http, clipboard, notification, os, process and the updater are
plugins: a JS package `@tauri-apps/plugin-<name>`, a Rust crate `tauri-plugin-<name>` registered with
`.plugin(...)`, and a permission in `src-tauri/capabilities/`.
- Opening URLs and files is `openUrl` / `openPath` from `@tauri-apps/plugin-opener`, not shell `open`.
- **Command arguments are camelCase from JS.** A Rust `fn save_note(note_title: String)` is called with
`invoke("save_note", { noteTitle })`. Sending `note_title` fails with a missing-argument error. (Return values and
struct fields keep their serde names.)
- Config: there's no `tauri` or `package` key. `productName`, `version` and `identifier` are top level, the window
list and security settings live under `app`, `build.devPath` is `build.devUrl` and `build.distDir` is
`build.frontendDist`. Validate against the schema in `node_modules/@tauri-apps/cli/config.schema.json`.
- Rust: `get_webview_window`, `emit` (the `Emitter` trait), `app.path()`, `tauri::tray::TrayIconBuilder`,
`tauri::menu::MenuBuilder`, `WebviewWindowBuilder`. The builder goes in `lib.rs` as `pub fn run()` with
`#[cfg_attr(mobile, tauri::mobile_entry_point)]`, and `main.rs` only calls it.
- Docs for this version: https://v2.tauri.app/ (the migration guide is
https://v2.tauri.app/start/migrate/from-tauri-1/). Ignore tauri.app/v1 pages.
## Rules
- Write Tauri 2 code only. The `tauri-2-guard` skill has the full table.
- Every plugin needs all three parts: the npm package, the crate plus `.plugin(...)`, and the narrowest permission
that works. Never add `"fs:default"`-style wide grants to make an error go away; ask.
- Keep `app.security.csp`. Don't turn on `withGlobalTauri` to use `window.__TAURI__`; import from `@tauri-apps/api`.
- Don't change the Tauri version without asking.
## Before you say "done"
1. Run the `tauri-2-guard` scanner on `src`, `src-tauri` and `package.json`. It must report `0 error(s)`.
2. Type-check the front end (`npx tsc --noEmit`) and run its tests, mocking the IPC with `@tauri-apps/api/mocks`.
3. Validate `src-tauri/tauri.conf.json` against the CLI's config schema.
4. Run `cargo check --manifest-path src-tauri/Cargo.toml` where the system has the WebView libraries, and
`npm run tauri dev` if you changed windows, menus or the tray. Adapter CLAUDE.md Imports AGENTS.md for Claude Code. 11 lines
# CLAUDE.md
@AGENTS.md
## Claude Code notes
- Skills from this loadout live in `.claude/skills/`: `tauri-2-guard`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.
<!-- From SetupBay "Tauri 2 guard for Tauri 1 imports, config and Rust APIs" v1.0.0 — https://setupbay.com/loadouts/tauri-2-api-guard/ --> Adapter GEMINI.md Imports AGENTS.md for Gemini CLI. 11 lines
# GEMINI.md
@./AGENTS.md
## Gemini CLI notes
- Skills from this loadout live in `.agents/skills/`: `tauri-2-guard`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.
<!-- From SetupBay "Tauri 2 guard for Tauri 1 imports, config and Rust APIs" v1.0.0 — https://setupbay.com/loadouts/tauri-2-api-guard/ --> Cursor rule .cursor/rules/tauri-2-only.mdc Never/always table for the front end, Rust and tauri.conf.json. 25 lines
---
description: Tauri 2 only; no Tauri 1 imports, Rust APIs or config keys
globs: "src/**/*.ts,src/**/*.js,src/**/*.tsx,src/**/*.vue,src/**/*.svelte,src-tauri/**/*.rs,src-tauri/tauri.conf.json"
alwaysApply: false
---
This app uses Tauri 2. Never write Tauri 1 code.
| Never (Tauri 1) | Always (Tauri 2) |
|---|---|
| `import { invoke } from "@tauri-apps/api/tauri"` | `import { invoke } from "@tauri-apps/api/core"` |
| `appWindow.setTitle(...)` | `getCurrentWebviewWindow().setTitle(...)` (`@tauri-apps/api/webviewWindow`) |
| `@tauri-apps/api/fs`, `/dialog`, `/shell`, `/http` | `@tauri-apps/plugin-fs`, `-dialog`, `-shell`, `-http` (+ crate + permission) |
| shell `open(url)` | `openUrl(url)` from `@tauri-apps/plugin-opener` |
| `invoke("save_note", { note_title })` | `invoke("save_note", { noteTitle })` (camelCase) |
| `"allowlist"` | `src-tauri/capabilities/*.json` permissions |
| `"tauri": {...}`, `"package": {...}` | `"app": {...}`; top-level `productName`, `version`, `identifier` |
| `build.devPath`, `build.distDir` | `build.devUrl`, `build.frontendDist` |
| `app.get_window("main")` | `app.get_webview_window("main")` |
| `window.emit_all(...)` | `window.emit(...)` (`use tauri::Emitter`) |
| `SystemTray`, `CustomMenuItem`, `WindowBuilder` | `TrayIconBuilder`, `MenuItemBuilder`, `WebviewWindowBuilder` |
| `app.path_resolver()`, `tauri::api::*` | `app.path()`, the plugin crates |
- After editing, run the `tauri-2-guard` skill's scanner, the type-check and the config schema check. Skill skills/tauri-2-guard/SKILL.md Scan for Tauri 1 code, then type-check, test with mocked IPC and validate the config schema. 53 lines
---
name: tauri-2-guard
description: Check a Tauri 2 app for Tauri 1 code in the front end, the Rust side and tauri.conf.json (api/tauri imports, appWindow, the allowlist, get_window, emit_all, SystemTray) and for snake_case invoke arguments, then type-check, test with mocked IPC and validate the config schema. Use after writing or editing Tauri code, when invoke reports a missing argument, or when porting a Tauri 1 example.
---
# Tauri 2 guard
Most Tauri examples online are Tauri 1, and Tauri 2 changed the import paths, moved fs/dialog/shell/http into
plugins, replaced the allowlist with capabilities, renamed config keys and renamed core Rust APIs. One change bites
even in pure Tauri 2 code: JS must send command arguments in camelCase.
## 1. Confirm the version
- `src-tauri/Cargo.toml` must say `tauri = "2..."` and `package.json` `@tauri-apps/api` 2.x. If not, stop and ask.
## 2. Scan
```bash
python3 .agents/skills/tauri-2-guard/scripts/tauri2_guard.py src src-tauri package.json
```
(Use the path the skill was installed to: `.claude/skills/...` for Claude Code, `.agents/skills/...` for the others.)
- Each `error` is Tauri 1 code. Fix it with the replacement on the line, or look it up in `references/v1-to-v2.md`.
- `warn [invoke-snake-args]`: rename the keys to camelCase, unless the Rust command has
`#[tauri::command(rename_all = "snake_case")]`. Then add `// guard: ok rename_all` to the line.
- `warn [global-tauri]`: import from `@tauri-apps/api` instead of using `window.__TAURI__`.
- When a plugin import is reported, add all three parts: the npm package, the crate plus `.plugin(...)`, and a
narrow permission in `src-tauri/capabilities/`.
## 3. Check the front end
```bash
npx tsc --noEmit
```
Test calls to Rust without running the app, using the mocks that ship with `@tauri-apps/api`:
```js
globalThis.window ??= globalThis; // only when the test runs in Node
const { mockIPC, mockWindows } = await import("@tauri-apps/api/mocks");
mockWindows("main");
mockIPC((cmd, args) => (cmd === "save_note" ? `saved ${args.noteTitle}` : null));
```
Assert on the command name and the argument keys, so a snake_case key fails the test.
## 4. Validate the config
`node_modules/@tauri-apps/cli/config.schema.json` is the schema for this exact CLI version, and it rejects unknown
keys. Validate `src-tauri/tauri.conf.json` against it with any JSON Schema (draft-07) validator. With Ajv, pass
`unicodeRegExp: false`, because the schema has a pattern that isn't valid as a Unicode regex.
## 5. Check the Rust side
`cargo check --manifest-path src-tauri/Cargo.toml` needs the platform WebView libraries (on Linux, webkit2gtk-4.1).
Where they aren't installed, say so in your report rather than claiming the Rust side compiles.
## 6. Report
Say which Tauri 1 calls and keys you replaced, which plugins and permissions you added, and which checks ran
(scanner, tsc, tests, schema, cargo check). Skill file skills/tauri-2-guard/scripts/tauri2_guard.py Read-only scanner for Tauri 1 imports, config keys, Rust APIs and snake_case invoke arguments. 160 lines
#!/usr/bin/env python3
"""Find Tauri 1 APIs, imports and config keys in a Tauri 2 app (front end, src-tauri Rust, tauri.conf.json, manifests).
Usage: python3 tauri2_guard.py [PATH ...] (default: the current folder)
python3 tauri2_guard.py --list (print every rule)
A "guard: ok" comment on a line silences its warnings (never its errors).
Prints one line per finding: path:line: level [rule] what is wrong -> what to use
Exit 0 when nothing at "error" level is found, 1 when something is, 2 on bad usage.
Standard library only. Read-only: it never edits a file and makes no network calls.
"""
import fnmatch
import os
import re
import sys
# (rule id, level, regex, message, file patterns). Patterns run against each line with comments removed.
RULES = [
('api-tauri-module', 'error', '[\\"\']@tauri-apps/api/tauri[\\"\']',
'@tauri-apps/api/tauri was renamed -> @tauri-apps/api/core (invoke, convertFileSrc)', ['*.ts', '*.tsx', '*.js', '*.mjs', '*.jsx', '*.vue', '*.svelte']),
('api-plugin-module', 'error', '[\\"\']@tauri-apps/api/(fs|dialog|shell|http|clipboard|notification|globalShortcut|os|process|updater|cli)[\\"\']',
'this module moved to a plugin in Tauri 2 -> @tauri-apps/plugin-<name> plus the Rust crate tauri-plugin-<name> and a capability permission', ['*.ts', '*.tsx', '*.js', '*.mjs', '*.jsx', '*.vue', '*.svelte']),
('app-window', 'error', '\\bappWindow\\b',
'appWindow was removed -> getCurrentWebviewWindow() from @tauri-apps/api/webviewWindow (or getCurrentWindow() from /window)', ['*.ts', '*.tsx', '*.js', '*.mjs', '*.jsx', '*.vue', '*.svelte']),
('webview-window-import', 'error', 'import\\s*\\{[^}]*\\bWebviewWindow\\b[^}]*\\}\\s*from\\s*[\\"\']@tauri-apps/api/window[\\"\']',
'WebviewWindow moved -> import it from @tauri-apps/api/webviewWindow', ['*.ts', '*.tsx', '*.js', '*.mjs', '*.jsx', '*.vue', '*.svelte']),
('invoke-snake-args', 'warn', 'invoke\\(\\s*[\\"\'][^\\"\']+[\\"\']\\s*,\\s*\\{[^}]*\\b[a-z0-9]+_[a-z0-9_]+\\s*:',
'Tauri command arguments are camelCase on the JS side by default (Rust note_title -> JS noteTitle), unless the command uses rename_all = "snake_case"', ['*.ts', '*.tsx', '*.js', '*.mjs', '*.jsx', '*.vue', '*.svelte']),
('global-tauri', 'warn', 'window\\.__TAURI__\\b',
'window.__TAURI__ only exists with app.withGlobalTauri: true -> import from @tauri-apps/api instead', ['*.ts', '*.tsx', '*.js', '*.mjs', '*.jsx', '*.vue', '*.svelte']),
('shell-open-url', 'warn', 'import\\s*\\{[^}]*\\bopen\\b[^}]*\\}\\s*from\\s*[\\"\']@tauri-apps/plugin-shell[\\"\']',
'shell open() is deprecated for URLs and files -> openUrl / openPath from @tauri-apps/plugin-opener', ['*.ts', '*.tsx', '*.js', '*.mjs', '*.jsx', '*.vue', '*.svelte']),
('conf-allowlist', 'error', '\\"allowlist\\"\\s*:',
'the allowlist was replaced by capabilities -> src-tauri/capabilities/*.json with plugin permissions', ['tauri.conf.json']),
('conf-tauri-key', 'error', '^\\s{0,4}\\"tauri\\"\\s*:\\s*\\{',
'the top-level "tauri" object was renamed -> "app" (and bundle moves to the top level)', ['tauri.conf.json']),
('conf-dist-dir', 'error', '\\"distDir\\"\\s*:',
'build.distDir was renamed -> build.frontendDist', ['tauri.conf.json']),
('conf-dev-path', 'error', '\\"devPath\\"\\s*:',
'build.devPath was renamed -> build.devUrl', ['tauri.conf.json']),
('conf-package', 'error', '^\\s{0,4}\\"package\\"\\s*:\\s*\\{',
'the "package" object was removed -> top-level productName and version', ['tauri.conf.json']),
('conf-system-tray', 'error', '\\"systemTray\\"\\s*:',
'systemTray was renamed -> app.trayIcon (or build it in Rust with TrayIconBuilder)', ['tauri.conf.json']),
('conf-updater', 'error', '\\"updater\\"\\s*:\\s*\\{\\s*\\"active\\"',
'the built-in updater moved to a plugin -> plugins.updater and tauri-plugin-updater', ['tauri.conf.json']),
('rs-get-window', 'error', '\\.get_window\\(',
'get_window() only exists behind the unstable feature in Tauri 2 -> get_webview_window()', ['*.rs']),
('rs-emit-all', 'error', '\\.emit_all\\(',
'emit_all() was removed -> emit() (to every target), or emit_to()', ['*.rs']),
('rs-system-tray', 'error', '\\bSystemTray(Event|Menu|MenuItem)?\\b',
'SystemTray was replaced -> tauri::tray::TrayIconBuilder (feature tray-icon)', ['*.rs']),
('rs-window-builder', 'error', '\\bWindowBuilder::new\\(',
'WindowBuilder::new was replaced -> WebviewWindowBuilder::new(app, label, WebviewUrl::App(...))', ['*.rs']),
('rs-custom-menu', 'error', '\\bCustomMenuItem\\b|\\bMenu::new\\(\\s*\\)',
'the Tauri 1 menu API was replaced -> tauri::menu::{MenuBuilder, MenuItemBuilder}', ['*.rs']),
('rs-api-module', 'error', '\\btauri::api::',
'tauri::api was removed -> the matching plugin crate (tauri-plugin-shell, -dialog, -fs, -http, -os, -process)', ['*.rs']),
('rs-path-resolver', 'error', '\\.path_resolver\\(\\)',
'path_resolver() was removed -> app.path() (the PathResolver from the Manager trait)', ['*.rs']),
('rs-window-param', 'warn', 'fn\\s+\\w+\\s*\\([^)]*:\\s*tauri::Window\\b',
'commands get a WebviewWindow in Tauri 2 -> window: tauri::WebviewWindow', ['*.rs']),
('cargo-tauri-1', 'error', '^\\s*tauri(-build)?\\s*=\\s*(\\{[^}]*version\\s*=\\s*)?\\"[~^=]?1\\.',
'Cargo.toml pins Tauri 1 -> tauri = "2" and tauri-build = "2"', ['Cargo.toml']),
('npm-tauri-1', 'error', '\\"@tauri-apps/(api|cli)\\"\\s*:\\s*\\"[~^]?1\\.',
'package.json pins Tauri 1 -> @tauri-apps/api and @tauri-apps/cli 2.x', ['package.json']),
]
FILES = ['*.ts', '*.tsx', '*.js', '*.mjs', '*.jsx', '*.vue', '*.svelte', '*.rs', 'tauri.conf.json', 'Cargo.toml', 'package.json']
COMMENT = '//'
SKIP_DIRS = {".git", ".venv", "venv", "node_modules", "__pycache__", ".agents", ".claude", ".cursor", "dist", "build", "target", ".godot"}
COMPILED = [(rid, lvl, re.compile(rx), msg, globs) for rid, lvl, rx, msg, globs in RULES]
def strip_comment(line):
"""Drop a trailing comment, leaving string literals alone."""
q = None
i = 0
while i < len(line):
c = line[i]
if q:
if c == "\\":
i += 2
continue
if c == q:
q = None
elif c in "\"'`":
q = c
elif line.startswith(COMMENT, i):
return line[:i]
i += 1
return line
def wanted(name):
return any(fnmatch.fnmatch(name, g) for g in FILES)
def walk(paths):
for p in paths:
if os.path.isfile(p):
yield p
continue
for root, dirs, files in os.walk(p):
dirs[:] = sorted(d for d in dirs if d not in SKIP_DIRS)
for f in sorted(files):
if wanted(f):
yield os.path.join(root, f)
def scan(path):
out = []
name = os.path.basename(path)
try:
with open(path, encoding="utf-8", errors="replace") as fh:
lines = fh.read().splitlines()
except OSError as e:
return [(path, 0, "error", "unreadable", str(e))]
for n, raw in enumerate(lines, 1):
code = strip_comment(raw)
if not code.strip():
continue
accepted = "guard: ok" in raw # a person accepted the warnings on this line
for rid, lvl, rx, msg, globs in COMPILED:
if accepted and lvl == "warn":
continue
if globs and not any(fnmatch.fnmatch(name, g) for g in globs):
continue
if rx.search(code):
out.append((path, n, lvl, rid, msg))
return out
def main(argv):
if "--list" in argv:
for rid, lvl, _, msg, globs in RULES:
print(f"{lvl:5} [{rid}] {msg}" + (f" (only {', '.join(globs)})" if globs else ""))
return 0
if any(a.startswith("-") for a in argv):
print(__doc__)
return 2
paths = argv or ["."]
for p in paths:
if not os.path.exists(p):
print(f"no such path: {p}", file=sys.stderr)
return 2
files = list(walk(paths))
findings = []
for f in files:
findings.extend(scan(f))
for path, n, lvl, rid, msg in findings:
print(f"{os.path.relpath(path)}:{n}: {lvl} [{rid}] {msg}")
errors = sum(1 for x in findings if x[2] == "error")
warns = sum(1 for x in findings if x[2] == "warn")
print(f"tauri2_guard: {len(files)} file(s), {errors} error(s), {warns} warning(s)")
return 1 if errors else 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:])) Skill file skills/tauri-2-guard/references/v1-to-v2.md Tauri 1 to Tauri 2 tables for the front end, the config and Rust. 45 lines
# Tauri 1 to Tauri 2, the code agents get wrong
From the official guide (https://v2.tauri.app/start/migrate/from-tauri-1/). Checked against `@tauri-apps/api` 2.12.4,
`@tauri-apps/cli` 2.12.4 (config schema 2.12.5) and the `tauri` 2.12.5 crate source.
## Front end
| Tauri 1 | Tauri 2 |
|---|---|
| `import { invoke, convertFileSrc } from "@tauri-apps/api/tauri"` | `from "@tauri-apps/api/core"` |
| `import { appWindow } from "@tauri-apps/api/window"` | `getCurrentWebviewWindow()` from `@tauri-apps/api/webviewWindow` (or `getCurrentWindow()` from `/window`) |
| `WebviewWindow` from `@tauri-apps/api/window` | from `@tauri-apps/api/webviewWindow` |
| `@tauri-apps/api/fs` (`readTextFile(p, { dir })`) | `@tauri-apps/plugin-fs` (`readTextFile(p, { baseDir })`) |
| `@tauri-apps/api/dialog` | `@tauri-apps/plugin-dialog` |
| `@tauri-apps/api/shell` `open(url)` | `openUrl(url)` from `@tauri-apps/plugin-opener`; `Command` from `@tauri-apps/plugin-shell` |
| `@tauri-apps/api/http` | `@tauri-apps/plugin-http` (`fetch`) |
| `clipboard`, `notification`, `globalShortcut`, `os`, `process`, `updater`, `cli` | `@tauri-apps/plugin-clipboard-manager`, `-notification`, `-global-shortcut`, `-os`, `-process`, `-updater`, `-cli` |
| `invoke("cmd", { note_title })` | `invoke("cmd", { noteTitle })`: arguments are camelCase by default |
| `window.__TAURI__.*` | imports from `@tauri-apps/api` (the global needs `app.withGlobalTauri: true`) |
## tauri.conf.json
| Tauri 1 | Tauri 2 |
|---|---|
| `package.productName`, `package.version` | top-level `productName`, `version` |
| `tauri.bundle.identifier` | top-level `identifier` |
| `tauri` | `app` (windows, security, trayIcon); `bundle` moves to the top level |
| `tauri.allowlist` | `src-tauri/capabilities/*.json` with plugin permissions |
| `build.devPath` / `build.distDir` | `build.devUrl` / `build.frontendDist` |
| `build.withGlobalTauri` | `app.withGlobalTauri` |
| `tauri.systemTray` | `app.trayIcon` |
| `tauri.updater` | `plugins.updater` and `tauri-plugin-updater` |
## Rust
| Tauri 1 | Tauri 2 |
|---|---|
| `app.get_window("main")` | `app.get_webview_window("main")` (`get_window` needs the `unstable` feature) |
| `window.emit_all(event, payload)` | `window.emit(event, payload)` with `use tauri::Emitter` |
| `window: tauri::Window` in a command | `window: tauri::WebviewWindow` |
| `app.path_resolver().app_data_dir()` (Option) | `app.path().app_data_dir()` (Result) |
| `SystemTray::new().with_menu(...)` | `tauri::tray::TrayIconBuilder::new().menu(&menu).build(app)?` (feature `tray-icon`) |
| `Menu::new().add_item(CustomMenuItem::new(id, text))` | `MenuBuilder::new(app).item(&MenuItemBuilder::with_id(id, text).build(app)?).build()?` |
| `WindowBuilder::new(app, label, WindowUrl::App(..))` | `WebviewWindowBuilder::new(app, label, WebviewUrl::App(..))` |
| `tauri::api::shell::open`, `tauri::api::dialog` | the plugin crates |
| builder in `main.rs` | `pub fn run()` in `lib.rs` with `#[cfg_attr(mobile, tauri::mobile_entry_point)]` |
| `tauri = { version = "1", features = ["shell-open", ...] }` | `tauri = "2"` plus plugin crates; allowlist features are gone | Skill file skills/tauri-2-guard/references/tauri1-sample/main.ts.txt Tauri 1 front end for checking the guard. 24 lines
// Tauri 1 front end, used to check the guard. Every marked import is gone in Tauri 2.
import { invoke } from "@tauri-apps/api/tauri";
import { appWindow, WebviewWindow } from "@tauri-apps/api/window";
import { readTextFile, BaseDirectory } from "@tauri-apps/api/fs";
import { open } from "@tauri-apps/api/dialog";
import { open as openLink } from "@tauri-apps/api/shell";
export async function saveNote(title: string, body: string) {
await invoke("save_note", { note_title: title, body });
await appWindow.setTitle(`Notes: ${title}`);
}
export async function loadNote() {
const path = await open({ filters: [{ name: "Notes", extensions: ["md"] }] });
return readTextFile(path as string, { dir: BaseDirectory.AppData });
}
export function openHelp() {
new WebviewWindow("help", { url: "help.html" });
return openLink("https://tauri.app");
}
export const version = window.__TAURI__.app.getVersion(); Skill file skills/tauri-2-guard/references/tauri1-sample/main.rs.txt Tauri 1 main.rs for checking the guard. 27 lines
// Tauri 1 src-tauri/src/main.rs, used to check the guard.
use tauri::{CustomMenuItem, Manager, Menu, SystemTray, SystemTrayMenu, WindowBuilder, WindowUrl};
#[tauri::command]
fn save_note(window: tauri::Window, note_title: String, body: String) -> Result<(), String> {
let dir = window.app_handle().path_resolver().app_data_dir().ok_or("no app data dir")?;
std::fs::write(dir.join(format!("{note_title}.md")), body).map_err(|e| e.to_string())?;
window.emit_all("note-saved", note_title).map_err(|e| e.to_string())
}
fn main() {
let tray = SystemTray::new().with_menu(SystemTrayMenu::new());
let menu = Menu::new().add_item(CustomMenuItem::new("quit", "Quit"));
tauri::Builder::default()
.menu(menu)
.system_tray(tray)
.setup(|app| {
let main = app.get_window("main").unwrap();
WindowBuilder::new(app, "help", WindowUrl::App("help.html".into())).build()?;
tauri::api::shell::open(&main.shell_scope(), "https://tauri.app", None)?;
Ok(())
})
.invoke_handler(tauri::generate_handler![save_note])
.run(tauri::generate_context!())
.expect("error while running tauri application");
} Skill file skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt Tauri 1 tauri.conf.json for checking the guard. 26 lines
{
"build": {
"beforeDevCommand": "npm run dev",
"beforeBuildCommand": "npm run build",
"devPath": "http://localhost:1420",
"distDir": "../dist",
"withGlobalTauri": true
},
"package": {
"productName": "notes",
"version": "0.1.0"
},
"tauri": {
"allowlist": {
"all": false,
"fs": { "readFile": true, "scope": ["$APPDATA/*"] },
"dialog": { "open": true },
"shell": { "open": true }
},
"bundle": { "active": true, "identifier": "com.example.notes", "targets": "all" },
"systemTray": { "iconPath": "icons/icon.png" },
"updater": { "active": false },
"windows": [{ "title": "Notes", "width": 800, "height": 600 }]
}
} Skill file skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt Tauri 1 Cargo.toml for checking the guard. 13 lines
# Tauri 1 src-tauri/Cargo.toml, used to check the guard.
[package]
name = "notes"
version = "0.1.0"
edition = "2021"
[build-dependencies]
tauri-build = { version = "1.5", features = [] }
[dependencies]
tauri = { version = "1.8", features = ["shell-open", "dialog-open", "fs-read-file", "system-tray"] }
serde = { version = "1", features = ["derive"] } All files: source zip · Licence MIT · By SetupBay · First listed
Credits
Public work that inspired this loadout. The wording here is our own; follow the links for the originals.
Installing and checks
How do I install Tauri 2 guard for Tauri 1 imports, config and Rust APIs in Claude Code?
From your project root, put AGENTS.md, CLAUDE.md, skills/tauri-2-guard/SKILL.md at .claude/skills/tauri-2-guard/SKILL.md, skills/tauri-2-guard/scripts/tauri2_guard.py at .claude/skills/tauri-2-guard/scripts/tauri2_guard.py, skills/tauri-2-guard/references/v1-to-v2.md at .claude/skills/tauri-2-guard/references/v1-to-v2.md, skills/tauri-2-guard/references/tauri1-sample/main.ts.txt at .claude/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt, skills/tauri-2-guard/references/tauri1-sample/main.rs.txt at .claude/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt, skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt at .claude/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt, skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt at .claude/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt. The "Claude Code" tab on this page has the curl commands, or download https://setupbay.com/download/tauri-2-api-guard/claude-code.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install Tauri 2 guard for Tauri 1 imports, config and Rust APIs in Codex CLI?
From your project root, put AGENTS.md, skills/tauri-2-guard/SKILL.md at .agents/skills/tauri-2-guard/SKILL.md, skills/tauri-2-guard/scripts/tauri2_guard.py at .agents/skills/tauri-2-guard/scripts/tauri2_guard.py, skills/tauri-2-guard/references/v1-to-v2.md at .agents/skills/tauri-2-guard/references/v1-to-v2.md, skills/tauri-2-guard/references/tauri1-sample/main.ts.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt, skills/tauri-2-guard/references/tauri1-sample/main.rs.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt, skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt, skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt. The "Codex CLI" tab on this page has the curl commands, or download https://setupbay.com/download/tauri-2-api-guard/codex.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install Tauri 2 guard for Tauri 1 imports, config and Rust APIs in Cursor?
From your project root, put AGENTS.md, .cursor/rules/tauri-2-only.mdc, skills/tauri-2-guard/SKILL.md at .agents/skills/tauri-2-guard/SKILL.md, skills/tauri-2-guard/scripts/tauri2_guard.py at .agents/skills/tauri-2-guard/scripts/tauri2_guard.py, skills/tauri-2-guard/references/v1-to-v2.md at .agents/skills/tauri-2-guard/references/v1-to-v2.md, skills/tauri-2-guard/references/tauri1-sample/main.ts.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt, skills/tauri-2-guard/references/tauri1-sample/main.rs.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt, skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt, skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt. The "Cursor" tab on this page has the curl commands, or download https://setupbay.com/download/tauri-2-api-guard/cursor.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install Tauri 2 guard for Tauri 1 imports, config and Rust APIs in Gemini CLI?
From your project root, put AGENTS.md, GEMINI.md, skills/tauri-2-guard/SKILL.md at .agents/skills/tauri-2-guard/SKILL.md, skills/tauri-2-guard/scripts/tauri2_guard.py at .agents/skills/tauri-2-guard/scripts/tauri2_guard.py, skills/tauri-2-guard/references/v1-to-v2.md at .agents/skills/tauri-2-guard/references/v1-to-v2.md, skills/tauri-2-guard/references/tauri1-sample/main.ts.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt, skills/tauri-2-guard/references/tauri1-sample/main.rs.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt, skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt, skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt. The "Gemini CLI" tab on this page has the curl commands, or download https://setupbay.com/download/tauri-2-api-guard/gemini-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install Tauri 2 guard for Tauri 1 imports, config and Rust APIs in Antigravity CLI?
From your project root, put AGENTS.md, skills/tauri-2-guard/SKILL.md at .agents/skills/tauri-2-guard/SKILL.md, skills/tauri-2-guard/scripts/tauri2_guard.py at .agents/skills/tauri-2-guard/scripts/tauri2_guard.py, skills/tauri-2-guard/references/v1-to-v2.md at .agents/skills/tauri-2-guard/references/v1-to-v2.md, skills/tauri-2-guard/references/tauri1-sample/main.ts.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt, skills/tauri-2-guard/references/tauri1-sample/main.rs.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt, skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt, skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt. The "Antigravity CLI" tab on this page has the curl commands, or download https://setupbay.com/download/tauri-2-api-guard/antigravity-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install Tauri 2 guard for Tauri 1 imports, config and Rust APIs in GitHub Copilot?
From your project root, put AGENTS.md, skills/tauri-2-guard/SKILL.md at .agents/skills/tauri-2-guard/SKILL.md, skills/tauri-2-guard/scripts/tauri2_guard.py at .agents/skills/tauri-2-guard/scripts/tauri2_guard.py, skills/tauri-2-guard/references/v1-to-v2.md at .agents/skills/tauri-2-guard/references/v1-to-v2.md, skills/tauri-2-guard/references/tauri1-sample/main.ts.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/main.ts.txt, skills/tauri-2-guard/references/tauri1-sample/main.rs.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/main.rs.txt, skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/tauri.conf.json.txt, skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt at .agents/skills/tauri-2-guard/references/tauri1-sample/Cargo.toml.txt. The "GitHub Copilot" tab on this page has the curl commands, or download https://setupbay.com/download/tauri-2-api-guard/copilot.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
What has been checked in Tauri 2 guard for Tauri 1 imports, config and Rust APIs?
It passed the Level 1 automated install checks on 2026-10-29: the files parse, install to each agent's documented paths, and pass the safety scan. No AI agent has run it yet, so no agent pass or fail is claimed.
More for Claude Code, Codex, Cursor, Gemini CLI, Antigravity CLI and GitHub Copilot.