Repository navigation
developing a plugin
rdownloader plugin new scaffolds a plugin that builds, packages and passes conformance before
you change a line of it — so the first failure you see is about your code, not about the setup.
| Tool | Version |
|---|---|
| Rust | 1.99, Edition 2024 |
cargo-component |
0.21.1 — the version the bundled plugins are built with |
| Target |
wasm32-unknown-unknown (rustup target add) |
wasm-tools |
For the import check |
rdownloader plugin new --type resolver --out ./myhoster
cd myhoster
cargo component build --release --target wasm32-unknown-unknown--type takes every world of the contract, thirteen in all, and each has a page of its own under
Plugin development that goes from the scaffold to a published package:
--type |
What it does |
|---|---|
resolver |
Turns a hoster link into a downloadable address and checks links |
transfer |
Carries the bytes of a protocol the application does not know |
intake |
Turns text and URLs into LinkGrabber candidates |
intake-mirrors |
An intake parser that also states every source of a file |
crawler |
Turns one address into the files behind it |
remote-job |
Runs a job that lives at a provider and outlives the call |
auth |
Signs an account in through the provider's own flow |
oauth |
Signs an account in by OAuth and renews the token |
enricher |
Adds metadata to a link |
notifier |
Delivers notifications to one more destination |
postprocess |
Runs one more step after a package has been downloaded |
storage |
Uploads finished packages somewhere |
stream-transform |
Answers with an address and how its bytes become a file |
The directory name becomes the crate name and the manifest's provider slug; --name sets a
different one.
plugin newreads its templates fromsdk/templates, so run it from a checkout of the repository or from a directory holding a copy of that folder. A release binary on its own does not carry them.
The scaffold brings its own copy of the WIT contract, rdownloader:plugin@0.10.0, in wit/, so nothing about the build
needs a checkout of rDownloader, and its own Ed25519 key pair in plugin-signing.key — which
belongs in your secret store, not in version control. plugin new writes a .gitignore before
the key, listing plugin-signing.key, target/ and *.rdplug, so a first git add . leaves the
key out; keep those lines when you edit the file.
cargo component build --release --target wasm32-unknown-unknowncargo-component additionally needs the wasm32-wasip1 target for its own componentisation; the
finished plugin nevertheless imports only the WIT host contract.
A component that imports anything outside rdownloader:plugin is refused — when it is
packaged, and again when it is installed. That includes a wasi: interface pulled in by a
dependency you did not choose directly.
scripts/check-plugin-imports.sh reads the import section with wasm-tools and names the
offending interface. The CI workflow template runs the same check.
Each grant in [capabilities] is one WIT interface.
- A component importing an interface its manifest does not grant is refused at packaging time and again at install time, so asking for less than you use fails at build time, not at a user's download.
- Ask for exactly what you use. The plugin manager shows your grants to the person deciding whether to install you.
- The file system, other processes, and the network beyond your declared domains are not capabilities that happen to be denied. There is no interface for them.
The scaffold ships locales/en.json. English is the one language a localised plugin must
carry — a package with any locale file and no en.json is refused.
The interface is offered in German, English, Spanish and French, and the bundled plugins ship all
four as de.json, en.json, es.json and fr.json. A language a plugin lacks falls back to
English.
Each scaffold is a small, working plugin of its type rather than a set of signatures: a PIN
sign-in, a resumable chunked upload, a CRC-32 over a package, a bounded folder walk, a key read out
of a link's fragment. The promises the host makes to the type are written at the top of
src/lib.rs; they are what shapes the code, so read them before changing it.
Everything that can run without a WebAssembly toolchain lives outside the component, and
src/guest.rs — the translation into the contract's types — exists only on wasm32, so
cargo test runs a fresh scaffold's unit tests straight away:
rdownloader plugin new --type oauth --out ./myprovider
cd myprovider && cargo testEvery scaffold carries a README.md naming its files and the rules worth knowing first. The
templates themselves are in
sdk/templates.
rdownloader plugin conformance myhoster.rdplug --jsonAnswers machine-readably whether this application would run your package. Run it before you publish anything.
User-facing text never lives in the plugin as prose. It lives as a stable code, translated in the plugin's own catalogue — the same rule the application follows.
An error value a provider wrote that is not code-shaped is dropped whole rather than filtered: filtering keeps the digits of a leaked credential.
Read an HTTP status nothing else explains the way the bundled plugins do, so a person sees the same outcome whichever plugin served the link:
| Status | Category | Why |
|---|---|---|
401, 403
|
account-invalid — or a plain HTTP error (permanent) when the request carried no account |
A bot wall must not send anybody to fix credentials they never gave |
404, 410
|
permanent |
The file is gone for good; it is not retried. A link check still reports it offline
|
451 |
offline |
Withheld for legal reasons, often regionally; it is retried |
429 |
rate-limited, with the provider's Retry-After
|
|
5xx |
transient, with the provider's Retry-After where one was sent |
Take Retry-After in seconds, at most one day — the host holds every wait to a day anyway — and
read Retry-After: 0 as your own default wait, not as "retry at once".
rdownloader serve --plugin-development-modeaccepts unsigned packages. Package with --development to produce one. Local development only.
- The page of your type under Plugin development, from the table under Scaffolding
- Plugin overview — what each type may and may not do
- Plugin reference — the manifest field by field, every plugin type, the contract
- Packaging, signing and distribution
- Installing and trust
Reference in the repository:
sdk/README.md ·
rdownloader.wit,
the contract
Getting started
- Installation
- Building from source
- Translating rDownloader
- First run
- Your first download
- The interface
Using rDownloader
- The download queue
- Download history
- The LinkGrabber
- Site rules
- Hosters and accounts
- Usenet and NZB
- BitTorrent
- Video and audio downloads
- Image galleries
- Livestream recording
- FTP, SFTP and WebDAV
- Object storage
- Subscriptions
- Remote jobs
- Storage, categories and rules
- Watched folders
- Post-processing
- Bandwidth and power
- Notifications
- Automation
- Statistics
- Keyboard and accessibility
Integrations
- Browser extension
- Desktop capture agent
- Command line client
- REST API
- MCP server
- Automation tool compatibility
Operating
- Docker and NAS
- Synology NAS
- Reverse proxy
- Accounts, sessions and permissions
- Sign in with an identity provider
- External tools
- Backup and restore
- Updates
- Security and privacy
- Diagnostics and maintenance
- Troubleshooting
- Defaults and limits
- Support matrix
Plugins
Plugin development
- Developing a plugin
- Resolver
- Transfer backend
- Intake parser
- Intake parser with mirrors
- Folder crawler
- Remote job
- Sign-in
- OAuth sign-in
- Metadata enricher
- Notification destination
- Post-processing step
- Upload destination
- Stream transform
- Plugin reference
- Packaging, signing and distribution
- Running a plugin repository
Reference