# Other toolchains (unsupported)
Rust with `standard-plugin-sdk` is the supported way to write a Standard
Code plugin. It is the only toolchain Standard Code tests or supports. The
other guides on these pages assume it: start with
[getting started](getting-started.md).
This page records the rules a component must meet, whatever built it. Use
of any other toolchain is possible, unsupported, and community territory.
## The contract
The contract is the WIT package `standard:plugin@2.0.0` in
[`wit/plugin.wit`](../wit/plugin.wit) in this crate.
It defines two worlds: `ui-plugin` for UI plugins and `daemon-plugin` for
daemon plugins and companions. The Rust SDK is one wrapper over that
package. [The low-level contract](abi.md) describes what the SDK does
over it: the exports, the memory rules and the surface buffer protocol.
## Rules for any component
- **A component.** The file the manifest's `module` names is a WebAssembly
component. `standard-plugin check` refuses a core module
(`src/component.rs` in `standard-plugin-cli`,
`inspect`).
- **Its world's imports only.** A component imports only the interfaces of
its kind's world. An import outside the world fails at instantiation
(`plugin.wit`, the package comment).
- **Its world's exports.** A UI plugin exports `activate`, `frame`,
`event` and `deactivate`. A daemon plugin exports `activate`, `event`,
`drive`, `deactivate` and the interfaces `daemon-events` and `companion`
([the low-level contract](abi.md#worlds-and-exports)).
- **No WASI in a UI half.** A UI plugin imports the `ui-plugin` world's
interfaces and nothing else. It imports no WASI interface of any
version. `check` reports every `wasi:` import of a UI half as an error
(`src/check.rs` in `standard-plugin-cli`,
`check_component`). This also rules out a libc or language runtime that
imports WASI.
- **WASI 0.2 in a daemon half, as the world states.** A daemon plugin may
import WASI 0.2 beside the `daemon-plugin` world. The world's comment in
`plugin.wit` lists what is linked: `wasi:filesystem` with the directories
the `fs.read:` and `fs.write:` grants name preopened (`/` under
`machine.full`), `wasi:http/outgoing-handler` to the hosts `fetch:`
grants name, `wasi:sockets` only under `network.full` or `machine.full`,
clocks, random, and stdout and stderr into the daemon's log. For
anything else, see the `daemon-plugin` world in `plugin.wit`. `check`
does not check which WASI interfaces a daemon half imports.
- **Sizes.** The component is at most 8 MiB and the manifest at most
64 KiB ([manifest](manifest.md)).
- **Memory.** The component exports its memory and the canonical ABI
realloc function, and follows the surface buffer protocol
([the low-level contract](abi.md#the-surface-buffer)).
## What the CLI does with a component
The `standard-plugin` CLI builds Rust crates. Its other commands read a
built component and do not care what built it
(`src/lib.rs` in `standard-plugin-cli`).
| `new` | yes | Writes a Rust crate from the SDK's examples. |
| `build` | yes | Runs `cargo build --lib --target wasm32-wasip2` on a crate with a `cdylib` target, copies the component into `bundle/` under the manifest's `module` name, then runs `check` (`src/build.rs` in `standard-plugin-cli`). |
| `check` | no | Parses the manifest, checks every grant, and checks the component in `bundle/` against its kind's world: imports, exports and WASI (`src/check.rs` in `standard-plugin-cli`). |
| `pack` | no | Runs `check`, then writes the deterministic package and prints its SHA-256 (`src/pack.rs` in `standard-plugin-cli`). |
| `install` | no | Runs `pack`, then `standard plugin install <dir>`, which asks before it installs. `STANDARD_BIN` names another `standard` binary (`src/install.rs` in `standard-plugin-cli`). |
| `guide` | no | Lists or prints these guides, as the SDK the plugin's `Cargo.lock` resolves carries them (`src/guide.rs` in `standard-plugin-cli`). |
Each command takes `--dir <path>` (the default is the current directory).
### The layout the CLI expects
A plugin directory holds its manifest and its component in `bundle/`:
```text
my-plugin/
bundle/
standard-plugin.json the manifest
<module> the component; the file name the manifest's "module" gives
```
`check` reads the component from `bundle/`. A manifest beside
`Cargo.toml` is copied into `bundle/` only by `build`, so without Cargo
keep both files in `bundle/`
(`src/project.rs` in `standard-plugin-cli`,
`Plugin`).
A companion pair is a parent directory whose immediate subdirectories are
the two plugins: one of kind `ui` and one of kind `companion`, with the
same `id`. The names of the subdirectories are free; the scaffold uses
`ui/` and `companion/`. `check`, `pack` and `install` on the parent
directory find both halves (`project::plugins`). In the package, `pack`
puts the halves under `ui/` and `daemon/`, each with its runtime manifest
and component ([publishing](publishing.md)).
## Toolchains
A component built by any toolchain that meets these rules can run.
Standard Code does not test or support other toolchains.
- C, C++ and Zig toolchains that build without a WASI-importing libc can
meet the UI rule.
- Toolchains that bundle an interpreter or a language runtime in the
component generally import WASI and make large components, so they
generally cannot meet the UI rule or the 8 MiB limit.