From 8efe8456125f21294f3f0b6504785fe6630b9341 Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Sun, 11 Oct 2026 22:07:25 -0300 Subject: [PATCH] chore: add AGENTS.md (#3680) * chore: add AGENTS.md * Apply batched suggestions from code review [skip ci] Co-authored-by: Amr Bashir * simplify --------- Co-authored-by: Amr Bashir --- AGENTS.md | 150 +++++++++++++++++++++++++++ plugins/haptics/guest-js/bindings.ts | 1 - 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..db7df6012 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,150 @@ +# AGENTS.md + +Instructions for coding agents working in this repository. The contributor guide is [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md). + +## Overview + +This repo holds the official [Tauri](https://tauri.app) plugins. Each directory in `plugins/` is one plugin, published as: + +- the Rust crate `tauri-plugin-` on crates.io, and +- the npm package `@tauri-apps/plugin-`, its JavaScript bindings for the webview, at the **same version** as the crate. + +Some plugins are Rust-only and have no npm package. + +Each Tauri major version has a branch here (`v1`, `v2`, …) with the plugins compatible with it. PRs go to the default branch. Don't port changes between them unless asked. + +## Layout + +```text +plugins// + build.rs lists the plugin's commands and generates its permissions + src/lib.rs init()/Builder, plus a `Ext` trait on AppHandle & co. + src/commands.rs #[tauri::command] handlers + src/desktop.rs, mobile.rs platform implementations; mobile.rs calls into Kotlin/Swift + src/error.rs thiserror Error, serialized to JS as its message string + src/models.rs serde types shared with JS and native code + permissions/*.toml hand-written permission sets, including default.toml + permissions/autogenerated/ generated + permissions/schemas/ generated + guest-js/index.ts JS API: thin wrappers around invoke('plugin:|') + api-iife.js generated: the window.__TAURI__. global (withGlobalTauri) + android/, ios/ native plugin code (Kotlin library, Swift package) + examples/ small per-plugin example apps +examples/api/ Svelte app that registers every plugin; the manual test bed +packages/api-e2e/ WebdriverIO e2e suite driven against examples/api +shared/rollup.config.js the rollup config every plugin builds with (createConfig) +shared/template/ skeleton for a new plugin ({{ placeholders }}, not compiled) +.changes/ covector change files +.scripts/ci/ scripts CI runs; they work locally too +``` + +## Build, lint, test + +Run everything from the repo root. + +```sh +pnpm install +pnpm build # every plugin: dist-js/, api-iife.js, src/init-iife.js +pnpm --filter @tauri-apps/plugin- build # one plugin +``` + +Run `pnpm build` before `pnpm lint`, `pnpm ts:check`, the example app or the e2e suite, because they read the plugins from `dist-js/`. + +Rust checks run per crate. CI runs them for every plugin a change affects, on Windows, Linux and macOS, and builds for iOS and Android: + +```sh +cargo clippy -p tauri-plugin- --all-targets -- -D warnings +cargo clippy -p tauri-plugin- --all-targets --all-features -- -D warnings +cargo test -p tauri-plugin- --all-targets --all-features +cargo test -p tauri-plugin- --doc +``` + +Some plugins have mutually exclusive features (check `[features]` in their `Cargo.toml`) and don't build with `--all-features`. Drop that flag for them. + +Formatting and JS checks. CI fails if any of them would change a file or report an error: + +```sh +cargo fmt --all +taplo fmt # TOML +pnpm format # prettier: TS, JS, JSON, Markdown, YAML +pnpm lint # eslint with type-aware rules +pnpm ts:check +``` + +To try a change by hand, run `pnpm example:api:dev`. It starts `examples/api` against the local plugins. + +The e2e suite runs with `pnpm test:api-e2e` (`test:api-e2e:android` and `test:api-e2e:ios` for mobile). Its prerequisites, environment variables and how to add a spec are in [packages/api-e2e/README.md](packages/api-e2e/README.md). + +## Generated files + +Don't edit these by hand. Regenerate them and commit the result together with the change that caused it. + +| Files | Regenerated by | +| ------------------------------------------------------------------------------------- | ------------------------------------------------------------ | +| `plugins/*/api-iife.js`, `plugins/*/src/init-iife.js` | `pnpm build`. CI fails if the build leaves a diff. | +| `plugins/*/permissions/autogenerated/**`, `plugins/*/permissions/schemas/schema.json` | the plugin's `build.rs`, on any `cargo check` or build of it | +| `CHANGELOG.md` files, package versions, the `version` of path dependencies | covector, at release time. Don't bump versions in a PR. | + +Also leave `dist-js/` alone, along with the git-ignored `.tauri/` directories under `plugins/*/` and `plugins/*/android/`. The build copies Tauri's mobile API into those. + +## Adding or changing a command + +These places must agree: + +1. `src/commands.rs`: write the `#[tauri::command]`, returning `crate::Result`. +2. `src/lib.rs`: register it in `tauri::generate_handler![…]` on every platform where the JS API exposes it. If it can't work on a platform, register it anyway and return an error there. An unregistered command reaches JS as an opaque "command not found". +3. `build.rs`: add it to `COMMANDS`, which generates its `allow-…` and `deny-…` permissions. Without them, apps can't grant it. When you remove a command, also delete its file from `permissions/autogenerated/commands/`, because the build doesn't remove stale ones. +4. `permissions/default.toml`: add it only if every app should get it without opting in. Defaults are deliberately narrow. +5. `guest-js/index.ts`: call `invoke('plugin:|', { … })`. JS passes the command's snake_case parameters as camelCase keys (`file_path` becomes `filePath`), and serde structs use `#[serde(rename_all = "camelCase")]`. Give exported functions TSDoc with an `@example`, and set `@since` to the version the change will ship in. +6. Mobile: `mobile.rs` forwards with `run_mobile_plugin("", args)` to the Kotlin `@Command` or Swift `@objc` method of that name. +7. Example app: if it should use the command, grant it in `examples/api/src-tauri/capabilities/` and cover it in `packages/api-e2e`. +8. Run `cargo check -p tauri-plugin-` and `pnpm build`, then commit the regenerated files. + +## Change files + +A change to a published crate or npm package needs a [covector](https://github.com/jbolda/covector) change file in `.changes/`. Changes that only touch CI, tests, examples or docs don't. Here is a real one, `.changes/fix-fs-read-lines-error.md`: + +```md +--- +fs: patch +fs-js: patch +--- + +Fixed `readTextFileLines` yielding empty lines forever when reading fails (e.g. on a directory). The read error is now reported: the iterator rejects and the file is closed. +``` + +- The keys are package names from `.changes/config.json`. `` is the crate and `-js` is the npm package. +- **List both with the same bump, even when only the Rust side or only the JS side changed.** Their versions are kept identical. Rust-only plugins have no `-js` entry. +- The bump is `patch`, `minor` or `major`. Plugins that depend on the changed one (`dialog` on `fs`, for example) are bumped automatically, so don't list them. +- The body becomes the changelog entry. Write it for the plugin's users: what changed, and what they must update. +- Check the file with `node .scripts/ci/check-change-files.js .changes/.md`. + +## Rules and gotchas + +- **License header:** new `.rs`, `.ts`, `.js`, `.kt`, `.swift` and `.yml` files must start with these lines (with `#` comments in YAML). Keep the year range exactly as written: + + ```text + // Copyright 2019-2023 Tauri Programme within The Commons Conservancy + // SPDX-License-Identifier: Apache-2.0 + // SPDX-License-Identifier: MIT + ``` + + Check new files with `node .scripts/ci/check-license-header.js `. Without arguments, it also reports the git-ignored `.tauri/` copies, which you can ignore. + +- **MSRV:** the tests run on exactly on MSRV configured in Cargo.toml (clippy runs on stable). Don't use newer std APIs, and check with `cargo + check -p tauri-plugin-` where is the current MSRV for the plugin. +- **tauri features:** the workspace depends on `tauri` with `default-features = false`. A plugin that needs a tauri feature, such as `wry` on iOS, enables it in its own `Cargo.toml`. Build plugins with `-p`: a workspace-wide build unifies features with `examples/api`, which hides a missing one. +- **Platform cfgs:** use the `desktop` and `mobile` cfgs that `tauri-plugin`'s build script sets, and `target_os` for single platforms. Desktop-only dependencies go in the long `cfg(any(target_os = "macos", windows, target_os = "linux", …))` target table that the existing manifests use. +- **docs.rs:** a plugin with mobile code must detect docs.rs in its `build.rs` with `std::env::var_os("DOCS_RS")`, as `plugins/dialog/build.rs` does. `cfg!(docsrs)` is never set for build scripts, and `shared/template/build.rs` still has that old form. +- **Dependencies:** shared ones come from `[workspace.dependencies]` (`serde = { workspace = true }`). A plugin that depends on another uses a path plus a version (`tauri-plugin-fs = { path = "../fs", version = "2.6.0" }`). +- **Updates:** Renovate handles routine dependency updates, so don't run a blanket `cargo update` or `pnpm update`. Unrelated lockfile changes make CI build and test every plugin. +- **New npm versions:** pnpm won't install versions published less than 3 days ago (`minimumReleaseAge`). Ask before adding an exception to `pnpm-workspace.yaml`. +- **Platform support:** when a plugin gains or loses a platform, update `[package.metadata.platforms.support]` in its `Cargo.toml`, the table in its README and the table in the root README. +- **Mirrors:** plugins listed in `plugins/mirrors.txt` are pushed to read-only `tauri-apps/tauri-plugin-` repositories. Make changes here, not in the mirrors. +- **Security:** report vulnerabilities privately, as [SECURITY.md](SECURITY.md) describes. Never put them in a public issue or PR. + +## Commits and pull requests + +- Use conventional-commit titles scoped to the plugin: `fix(fs): …`, `feat(notification): …`, `chore(deps): …`, `ci: …`, `docs(log): …`. When the change fixes an issue, end the title with `(fix #1234)`. +- Commits must be signed, so don't bypass signing. PRs are squash-merged, so intermediate commits are fine. +- A new feature needs a convincing reason, ideally an issue the maintainers accepted. Link it in the PR. +- [AI tool policy](.github/CONTRIBUTING.md#ai-tool-policy): the person submitting is responsible for everything an agent wrote, and replies to review comments must not be AI-written (translations excepted). PRs that ignore this are closed as `ai-slop`. Before handing work over, run the checks above and say plainly what you tested and on which platforms. Don't draft or post replies to review comments. diff --git a/plugins/haptics/guest-js/bindings.ts b/plugins/haptics/guest-js/bindings.ts index 040e27861..3da71c4e5 100644 --- a/plugins/haptics/guest-js/bindings.ts +++ b/plugins/haptics/guest-js/bindings.ts @@ -3,7 +3,6 @@ // SPDX-License-Identifier: MIT // @ts-nocheck -// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually. /** user-defined commands **/