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)
JSON-RPC

risuko-engine (Rust crate)

Config Module
Engine Manager
Protocol Handlers
HTTP, BT (risuko-bt), ED2K, M3U8, FTP, RSS
RPC Server
Events Broadcast
Traits
ConfigDir, Events, Storage

Cargo Workspace

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

CrateTypeDescription
risuko-engineLibraryCore engine with zero runtime dependencies
risuko-btLibraryIn-tree BitTorrent v1 engine consumed by risuko-engine
risuko-cliBinaryStandalone CLI tool
risuko-napicdylibNative Node.js bindings
risuko (root)BinaryTauri desktop application
[workspace]
members = ["risuko-engine", "risuko-bt", "risuko-cli", "risuko-napi"]

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 risuko-cli and 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.

On this page