Risuko
Architecture

Architecture

How Risuko is structured — the engine, traits, and distribution model.

Risuko follows a layered architecture where the core download engine is fully decoupled from any runtime environment.

High-Level Structure

Consumers

Desktop App
(Tauri + Vue)
CLI
(risuko-cli)
Node.js API
(risuko-js)
in-process (Tauri commands, NAPI) · JSON-RPC (CLI, external clients)

risuko-engine (Rust crate)

Config Module
Engine Manager
Protocol Handlers
HTTP, BT (risuko-bt), ED2K, M3U8, FTP/SFTP, Media (yt-dlp), ADC/DC, Gnutella, G2, giFT, RSS, Upload Sinks
RPC Server
Events Broadcast
Stats Manager
desktop download-history samples
Traits
ConfigDir, Events, Storage

Cargo Workspace

The project is organized as a Cargo workspace with nine crates:

CrateTypeDescription
risuko-engineLibraryCore engine — protocol handlers, RPC server, RSS, upload sinks, download stats store
risuko-btLibraryIn-tree BitTorrent engine (v1, v2 per BEP 52, and hybrid) consumed by risuko-engine
risuko-httpLibraryMinimal hyper v1 HTTP client (TLS pool, SOCKS5/HTTP proxy, redirects, cookies, gzip/br/deflate decompression, pluggable DNS resolver with optional DNS-over-HTTPS) — no reqwest dep
risuko-cookiesLibraryBrowser cookie extraction (Chromium, Firefox, Safari families)
risuko-shareLibraryPeer-to-peer encrypted file sharing built on iroh
risuko-webview-upgradeLibraryTauri plugin that swaps in a newer WebView kernel on Android
risuko-cliBinaryStandalone CLI tool
risuko-napicdylibNative Node.js bindings
risuko (root)BinaryTauri desktop application
[workspace]
members = ["risuko-engine", "risuko-bt", "risuko-cli", "risuko-napi", "risuko-http", "risuko-cookies", "risuko-webview-upgrade", "risuko-share"]

Key Design Decisions

Trait-Based Decoupling

The engine uses three traits to abstract away runtime-specific behavior. This lets the same engine code run inside Tauri, as a standalone CLI, or embedded in Node.js.

See Trait System for details.

JSON-RPC for CLI

The CLI communicates with the engine via JSON-RPC over HTTP. This means:

  • The serve command starts a headless engine with an RPC server
  • All other commands are RPC clients
  • The download command auto-starts a temporary engine if none is running

Global Singleton for NAPI

The Node.js bindings use a global LazyLock<Mutex<Option<NapiEngine>>> singleton. This ensures only one engine instance exists per process, which matches the startEngine/stopEngine lifecycle API.

Platform-Specific npm Packages

Both the CLI (@risuko/cli) and the Node.js bindings (@risuko/risuko-js) use the esbuild distribution pattern: a main package with optionalDependencies pointing to platform-specific packages. npm automatically installs only the package matching the current platform. A third package, @risuko/app, is a launcher that downloads the desktop app from GitHub Releases on first run.

On this page