tauri-apps/tauri
Build smaller, faster, and more secure desktop and mobile applications with a web frontend.
Healthy across the board
- ✓Last commit today
- ✓5 active contributors
- ✓Distributed ownership (top contributor 34%)
- ✓Apache-2.0 licensed
- ✓CI configured
- ✓Tests present
- ⚠Small team — 5 top contributors
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Embed this verdict
[](https://repopilot.app/r/tauri-apps/tauri)Paste into your README — the badge live-updates from the latest cached analysis.
Onboarding doc
Onboarding: tauri-apps/tauri
Generated by RepoPilot · 2026-05-05 · Source
Verdict
GO — Healthy across the board
- Last commit today
- 5 active contributors
- Distributed ownership (top contributor 34%)
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Small team — 5 top contributors
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
TL;DR
Tauri is a Rust-based framework for building native desktop and mobile applications using web technologies (HTML/CSS/JS) as the frontend, bundled with a Rust backend. Unlike Electron, it uses the OS-native WebView (WKWebView on macOS, WebView2 on Windows, WebKitGTK on Linux) instead of shipping Chromium, producing binaries that are dramatically smaller and more memory-efficient. It includes a built-in bundler (producing .app, .dmg, .deb, .rpm, .AppImage, NSIS .exe, WiX .msi), a self-updater, system tray, native notifications, and a capability-based ACL security model. Monorepo: core Rust crates live under crates/ (tauri, tauri-runtime, tauri-runtime-wry, tauri-utils, tauri-build, tauri-codegen, tauri-macros, tauri-plugin, tauri-bundler, tauri-cli, tauri-driver, tauri-macos-sign); the npm-facing CLI wrapper is at packages/cli; runnable examples are in examples/ (api, file-associations, resources); benchmarks are in bench/tests/. The TypeScript/JS plugin and IPC surface lives alongside the Rust crates rather than in a separate packages tree.
Who it's for
Web developers (React, Svelte, Vue, etc.) who want to ship cross-platform desktop or mobile apps without Electron's bundle size and memory overhead, and Rust developers who want to expose native system APIs to a web frontend via type-safe IPC commands with fine-grained permission control.
Maturity & risk
Tauri 2.0 is stable (badge shows 'status: stable'), has extensive CI across .github/workflows/ (audit, fmt, lint-rust, lint-js, test-core, bench, check-license-header, etc.), and the workspace includes integration tests under crates/tests/ and benchmarks under bench/. It is actively maintained by a named organization (The Commons Conservancy) with a full release pipeline (covector-version-or-publish.yml). Verdict: production-ready for desktop, with mobile support (Android/iOS via Kotlin/Swift code) actively maturing.
The project depends on platform WebViews meaning rendering consistency varies across OS versions — WebKitGTK on Linux is notably inconsistent across distros. The Cargo workspace has a patched fork of schemars (via patch.crates-io pointing to tauri-apps/schemars feat/preserve-description-newlines branch), which is an upstream-divergence risk. Mobile support (Kotlin at 72K LOC, Swift at 25K LOC) is newer than the desktop path and may have rougher edges.
Active areas of work
Active work visible in .changes/ includes: enforcing ACL remote origins (enforce-acl-remote-origins.md), exposing mobile monitor APIs (expose-mobile-monitor-apis.md), fixing request-permission on Android (fix-request-permission-android.md), a localhost suffix security fix (tauri-sec-localhost-suffix.md), phf 0.13 upgrade (phf-0.13.md), and a driver arg eq-separator fix (driver-arg-eq-separator.md).
Get running
Prerequisites: Rust 1.77.2+, Node.js, platform WebView dev deps
git clone https://github.com/tauri-apps/tauri.git cd tauri
Build the core Rust workspace
cargo build
Run the API example app (requires a JS build step first)
cd examples/api/src-tauri cargo tauri dev
Or install the CLI globally via npm
npm install -g @tauri-apps/cli npx create-tauri-app@latest
Daily commands:
Dev mode for the included API example:
cd examples/api/src-tauri && cargo tauri dev
Run Rust tests across the workspace:
cargo test --workspace
Run benchmarks:
cd bench && cargo bench
Lint Rust:
cargo clippy --workspace
Lint JS (from repo root, uses workflow lint-js.yml which calls eslint):
npm run lint # inside packages/cli or examples/api
Map of the codebase
crates/tauri/src/lib.rs— Root entry point for the tauri crate — defines the public API surface, re-exports core types, and wires together the application builder pattern that every Tauri app depends on.crates/tauri-runtime/src/lib.rs— Defines the Runtime trait abstraction layer that decouples the core tauri crate from the concrete webview backend (wry), making it the central interface every platform implementation must satisfy.crates/tauri-runtime-wry/src/lib.rs— The concrete Wry-backed runtime implementation — the actual bridge between Tauri's abstractions and the OS-level webview, window management, and event loop.Cargo.toml— Workspace root manifest defining all member crates, shared dependency versions, and feature flags — essential for understanding the overall project structure and build graph.crates/tauri-utils/src/lib.rs— Shared utility types and helpers (config parsing, assets, platform detection) used by nearly every other crate in the workspace.crates/tauri-macros/src/lib.rs— Procedural macros (command, generate_handler, etc.) that power Tauri's ergonomic command invocation system — understanding these is prerequisite to working with any IPC feature.ARCHITECTURE.md— High-level architectural documentation describing how the layers (core, runtime, bundler, CLI) relate to each other — the first file any new contributor should read.
How to make changes
Add a new Tauri IPC Command
- Define an async Rust function annotated with #[tauri::command] inside the src-tauri/src directory, accepting typed arguments and returning a Result. (
examples/api/src-tauri/src/main.rs) - Register the command in the generate_handler! macro call inside tauri::Builder::default().invoke_handler(...). (
examples/api/src-tauri/src/main.rs) - Review the #[command] procedural macro to understand how argument extraction and serialization are generated. (
crates/tauri-macros/src/lib.rs) - Call the command from the JavaScript frontend using the @tauri-apps/api invoke() helper. (
packages/cli/package.json)
Create a new Tauri Plugin
- Use tauri-plugin's Builder to scaffold a new plugin struct implementing the Plugin trait, registering commands and mobile bindings. (
crates/tauri-plugin/src/lib.rs) - Add a permissions/ACL schema for the plugin using the schema generator so the capability system can validate usage. (
crates/tauri-schema-generator/src/lib.rs) - Register the plugin with app.plugin(my_plugin::init()) in the application builder. (
examples/api/src-tauri/src/main.rs)
Add a new build-time asset / resource embedding
- Place the resource file in the src-tauri directory and declare it in tauri.conf.json under the bundle.resources field. (
examples/api/src-tauri/tauri.conf.json) - The tauri-build crate's build.rs helper will detect and embed the resource; review the embedding logic here. (
crates/tauri-build/src/lib.rs) - Use tauri-codegen to understand how assets are serialized into the binary at compile time. (
crates/tauri-codegen/src/lib.rs)
Add a new bundler output format (e.g. new installer type)
- Create a new module inside tauri-bundler implementing the packaging logic for the new format. (
crates/tauri-bundler/src/lib.rs) - Wire the new format into the CLI's build subcommand so it is selectable via --bundles flag. (
crates/tauri-cli/src/lib.rs) - Add any macOS-specific signing requirements by extending the signing utilities. (
crates/tauri-macos-sign/src/lib.rs)
Why these technologies
- Rust — Provides memory safety without a GC, enabling a small binary footprint and high performance for the native host process — critical for a framework selling itself on 'smaller and faster' than Electron.
- Wry (WebView library) — Thin cross-platform abstraction over OS-native webviews (WebKit on macOS/Linux, WebView2 on Windows) avoiding the need to ship Chromium and dramatically reducing bundle size.
- Tao (event loop) — Fork of winit providing a cross-platform windowing and event-loop API tuned for Tauri's needs including system tray and menu support missing from upstream winit.
- serde / serde_json — De-facto standard for Rust serialization; powers the entire IPC layer by serializing command arguments and return values across the JS/Rust boundary with zero manual parsing.
- TypeScript / Node.js (CLI wrapper) — Developers expect npm-centric tooling; the JS CLI wrapper lets users install and invoke tauri commands via npm/yarn/pnpm without needing to know Rust toolchain details.
Trade-offs already made
-
Use OS-native webviews instead of bundling Chromium
- Why: Reduces application size from ~150 MB (Electron) to under 10 MB.
- Consequence: Rendering inconsistencies across OS versions and webview implementations; developers must test on multiple platforms and cannot rely on a single known browser engine.
-
Capability-based ACL security model for IPC
- Why: Prevents malicious web content from calling arbitrary native commands; follows least-privilege principles.
- Consequence: Adds configuration overhead — developers must explicitly declare permissions in capability files, which has a learning curve and can cause confusing 'command not found' errors.
-
Separate tauri-runtime trait from tauri-runtime-wry implementation
- Why: Allows alternative runtime backends (e.g. headless, mock) and makes the core testable without a real webview.
- Consequence: Extra abstraction layer increases indirection when debugging runtime-level issues; contributors must understand two crates to trace a single window operation.
-
Embed frontend assets into the binary at compile time via tauri-codegen
- Why: Produces a single self-contained executable
- Consequence: undefined
Traps & gotchas
- Minimum Rust version is 1.77.2 (enforced via workspace.package.rust-version) — older toolchains silently produce confusing errors. 2) The schemars dependency is patched to a custom tauri-apps fork branch; if you add crates that depend on schemars you must ensure they resolve to the patched version or you'll get duplicate-type compilation errors. 3) Linux builds require libwebkit2gtk-4.1-dev and related GTK dev packages installed at the OS level — missing these gives cryptic pkg-config errors. 4) WebView2 on Windows must be present at runtime (ships with Windows 11, requires separate install on older Windows). 5) The release profile uses panic='abort' which affects how Rust panics behave in plugins — do not assume unwinding semantics.
Architecture
Concepts to learn
- WebView (OS-native) — Tauri's entire size advantage over Electron comes from delegating rendering to the OS-provided WebView (WKWebView, WebView2, WebKitGTK) rather than bundling Chromium — understanding the capability and quirk differences between these three is essential for debugging cross-platform rendering issues.
- Capability-based Access Control (ACL) — Tauri 2.0 uses a declarative capability/permission system (crates/tauri-utils/src/acl/) to restrict which IPC commands each window or webview can invoke — this is the primary security model and must be understood to correctly expose or restrict native APIs.
- Inter-Process Communication (IPC) over WebView message passing — All communication between the JS frontend and Rust backend goes through a string-serialized message channel injected into the WebView — the tauri::command macro and invoke() JS function are the two ends of this bridge, and understanding it is required to add any new native functionality.
- Procedural Macros (proc-macros) in Rust — crates/tauri-macros implements #[tauri::command] and #[tauri::generate_handler!] as proc-macros that generate IPC dispatch code at compile time — contributors adding commands or modifying the macro behavior must understand how proc-macros work.
- Link-Time Optimization (LTO) — The release profile sets lto=true and codegen-units=1, which is why Tauri binaries are small but release builds are slow — understanding this tradeoff helps explain CI build times and why incremental=false is set.
- NSIS (Nullsoft Scriptable Install System) — With 120K LOC of NSIS scripts, the Windows installer path is a significant part of the bundler — Windows packaging bugs almost always involve these scripts under crates/tauri-bundler/.
- Covector (monorepo versioning and publishing) — The release workflow uses covector (.changes/ directory + .github/workflows/covector-version-or-publish.yml) instead of conventional changesets or lerna — understanding it is required to correctly author a change file and trigger a release.
Related repos
electron/electron— The dominant alternative — also lets web developers build desktop apps but ships a full Chromium runtime, making it the size/memory tradeoff Tauri was built to avoid.tauri-apps/wry— The WebView rendering library Tauri uses internally (tauri-runtime-wry); changes here directly affect how Tauri renders content on all platforms.tauri-apps/tao— The cross-platform windowing library (fork of winit) used by tauri-runtime-wry for window creation and event loops.tauri-apps/create-tauri-app— The official project scaffolding CLI (npm create tauri-app) — the primary onboarding path for new Tauri users referencing this repo.nickel-lang/nickel— Predecessor inspiration — not directly related, but neutralino.js (neutralinojs/neutralinojs) is the closest lightweight-desktop-app competitor worth knowing for context.
PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for ACL remote origin enforcement in crates/tests/acl
The .changes/enforce-acl-remote-origins.md file indicates a recent feature was added to enforce ACL on remote origins. The existing crates/tests/acl directory suggests there is an integration test suite for ACL, but it likely lacks coverage for the new remote origin enforcement behavior. Adding tests here would catch regressions in a security-critical feature.
- [ ] Review .changes/enforce-acl-remote-origins.md to understand the exact behavior introduced
- [ ] Examine crates/tests/acl/src or equivalent to understand existing test patterns
- [ ] Add test cases in crates/tests/acl that configure a Tauri app with remote origins in the ACL and assert that commands are denied when called from disallowed origins
- [ ] Add test cases asserting commands are allowed when called from explicitly permitted remote origins
- [ ] Verify tests run correctly under the .github/workflows/test-core.yml workflow
Add a GitHub Actions workflow for end-to-end mobile (iOS) testing similar to test-android.yml
The .github/workflows directory contains test-android.yml for Android testing but there is no equivalent test-ios.yml workflow. Since Tauri supports mobile (as indicated by .changes/expose-mobile-monitor-apis.md and .changes/fix-request-permission-android.md), iOS CI coverage is a clear gap. This would prevent iOS-specific regressions from going undetected.
- [ ] Study .github/workflows/test-android.yml to understand the existing mobile test workflow structure
- [ ] Review .changes/expose-mobile-monitor-apis.md to identify which mobile APIs need iOS-specific test coverage
- [ ] Create .github/workflows/test-ios.yml using a macos-latest runner with Xcode and iOS simulator setup steps
- [ ] Mirror the job structure from test-android.yml adapting target to aarch64-apple-ios-sim and using xcrun simctl
- [ ] Add the new workflow to CODEOWNERS (.github/CODEOWNERS) under the appropriate team
- [ ] Confirm the workflow triggers on pull_request and push to dev for the relevant crate paths
Split crates/tauri-utils into focused sub-modules and add missing unit tests for the ACL and config parsing logic
tauri-utils is a large shared utility crate used by tauri, tauri-build, tauri-codegen, and tauri-cli. Given its broad scope (config parsing, ACL, assets, platform detection, etc.) it is likely a large monolithic file or module. Splitting it into focused sub-modules improves maintainability and discoverability, and adding unit tests for the ACL and config parsing paths (which are referenced by multiple .changes entries) ensures correctness for these security-sensitive areas.
- [ ] Audit crates/tauri-utils/src/lib.rs and subdirectory structure to identify modules that exceed a reasonable size or mix unrelated concerns
- [ ] Identify the ACL-related types and functions (referenced in .changes/enforce-acl-remote-origins.md) and confirm they have unit tests; add tests for edge cases such as wildcard origin matching and localhost suffix rules (.changes/tauri-sec-localhost-suffix.md)
- [ ] Identify the config deserialization logic and add unit tests covering malformed input, default values, and version migration paths
- [ ] If lib.rs is a flat file, refactor into sub-modules (e.g., acl.rs, config.rs, assets.rs, platform.rs) with pub use re-exports to maintain the existing public API
- [ ] Run the full test suite via cargo test -p tauri-utils and confirm no regressions
- [ ] Update .github/workflows/test-core.yml if new test features or feature flags are required
Good first issues
- crates/tests/ only contains 'restart' and 'acl' integration tests — adding an integration test for the self-updater flow in crates/tauri/src/updater/ would close a visible coverage gap. 2) The .changes/ directory uses markdown files to document unreleased changes but there is no lint/validation step to ensure every .changes/*.md file follows the required format (see .changes/config.json) — a GitHub Actions workflow to validate these on PRs would be a contained, useful addition. 3) The examples/api example app exercises many features but has no automated screenshot or smoke test — adding a tauri-driver-based end-to-end test (crates/tauri-driver already exists) for the API example would be a concrete, bounded contribution.
Top contributors
- @Legend-Master — 19 commits
- @lucasfernog — 14 commits
- @renovate[bot] — 12 commits
- @dependabot[bot] — 6 commits
- @FabianLars — 5 commits
Recent commits
5e3126f— feat(mobile): expose monitor APIs (#15338) (lucasfernog)ba02558— Merge commit from fork (chippers)5f479c0— fix(core): requestPermission crash regression on Android, closes #15323 (#15336) (lucasfernog)1b26769— fix(tauri): enforce ACL for remote origins even without AppManifest (#15266) (mtsgrd)3057eda— fix(driver): enableeq-separatorfeature forpico-args. (#15324) (Kokoro2336)4f548e7— chore(deps): update phf to 0.13 (#15308) (Legend-Master)4ca427d— fix: pin napi for msrv and Node.js on CI (#15310) (lucasfernog)a04d907— fix(ci): publish-cli-rs script for Powershell (#15309) (lucasfernog)e60834f— Apply Version Updates From Current Changes (#15041) (github-actions[bot])df05c00— chore: minor bump for codegen crate (lucasfernog)
Security observations
- Medium · Unvetted External Git Dependency Patch Override —
Cargo.toml ([patch.crates-io] section). The workspace Cargo.toml uses a [patch.crates-io] directive to replace 'schemars_derive' with a version sourced from an external GitHub repository (tauri-apps/schemars, branch 'feat/preserve-description-newlines'). Pinning to a branch rather than a specific commit hash means the dependency can change at any time without notice, potentially introducing malicious or vulnerable code if the upstream repository is compromised or the branch is force-pushed. Supply chain integrity cannot be guaranteed without a pinned commit SHA. Fix: Pin the patched dependency to a specific, reviewed commit SHA instead of a branch reference (e.g., rev = 'abc123...'). Additionally, consider running 'cargo vet' or equivalent supply-chain verification tooling and periodically auditing this dependency. Use 'Cargo.lock' to lock transitive dependencies and ensure reproducible builds. - Medium · LTO and Strip in Release May Obscure But Not Eliminate Vulnerabilities —
Cargo.toml ([profile.release] section). While LTO (lto = true) and binary stripping (strip = true) are good hardening practices for release builds, panic = 'abort' combined with these settings means that stack unwinding and debugging information are stripped. This can make post-incident forensic analysis and crash reporting more difficult, potentially slowing incident response when a vulnerability is exploited in production. Fix: Consider maintaining a separate debug-symbols artifact during CI/CD builds (using split-debuginfo) for forensic and crash analysis purposes while still shipping stripped binaries to end users. Ensure crash reporting integrations are configured where applicable. - Low · Docker Cross-Compilation Images with External Package Installation —
.docker/cross/ (Dockerfile, common.sh, dropbear.sh, qemu.sh). The .docker/cross/ directory contains Dockerfiles and shell scripts (common.sh, deny-debian-packages.sh, dropbear.sh, qemu.sh, etc.) that are used for cross-compilation. Shell scripts that install or configure system packages during Docker image builds (e.g., via apt-get or similar) without pinned package versions or checksum verification can introduce unintended packages or vulnerable versions into the build environment, indirectly affecting the security of produced binaries. Fix: Pin all installed package versions in Dockerfiles and shell scripts. Use hash verification (e.g., SHA256 checksums) for any downloaded binaries or archives. Prefer using multi-stage builds and minimal base images to reduce attack surface. Regularly update and audit base images. - Low · Sensitive Workflow Secrets Exposure Risk in GitHub Actions —
.github/workflows/ (covector-comment-on-fork.yml, covector-version-or-publish.yml, etc.). The repository contains numerous GitHub Actions workflow files (.github/workflows/). If any of these workflows use 'pull_request_target' triggers without proper restrictions, or if secrets are passed insecurely to forked PR builds, it could allow attackers to exfiltrate repository secrets. The presence of 'covector-comment-on-fork.yml' suggests workflows specifically designed for fork handling, which is a known risk vector. Fix: Audit all workflow files for use of 'pull_request_target' and ensure secrets are not accessible in contexts where untrusted code could run. Use environment-level secret protection and require approvals for workflows triggered from forks. Follow GitHub's hardening guides for Actions (e.g., pin Actions to commit SHAs, use CODEOWNERS for workflow changes). - Low · Publicly Exposed Security Audit Configuration —
.cargo/audit.toml. The .cargo/audit.toml file is visible in the repository. While this is generally acceptable and even encouraged for transparency, any ignored or suppressed advisories in this file could represent known vulnerabilities that are accepted without full remediation. If advisories are suppressed without documented justification, this could mask real risks. Fix: Review the contents of .cargo/audit.toml to ensure no critical or high-severity advisories are being suppressed without documented justification and a clear remediation plan. Run 'cargo audit' in CI and treat new advisories as blocking issues. Document any exceptions with reasoning and expiration dates. - Low · Inclusion of Example Applications with Potential Broad API Surface —
undefined. The workspace includes example applications (examples/api/src-tauri, examples/file-associations/src-tauri, etc.) Fix: undefined
LLM-derived; treat as a starting point, not a security audit.
Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.