Risuko
Configuration

Configuration

Risuko configuration reference — all available options.

Risuko stores configuration in two JSON files in the config directory:

  • system.json — System-level defaults (created on first run)
  • user.json — User overrides

User settings take precedence over system defaults.

Config Directory Locations

EnvironmentPath
macOS~/Library/Application Support/dev.risuko.app
Linux~/.config/dev.risuko.app
Windows%APPDATA%\dev.risuko.app
Desktop AppManaged by Tauri (platform-specific app data)
Node.js APIConfigurable via EngineConfig.configDir

Reading Configuration

CLI

# List all settings
risuko config list

# Get a specific value
risuko config get dir

# JSON output
risuko config list --json

Node.js

import { getGlobalOption } from "@risuko/risuko-js";

const options = await getGlobalOption();
console.log(options.dir);
console.log(options["max-concurrent-downloads"]);

Writing Configuration

CLI

risuko config set dir '"/home/user/downloads"'
risuko config set max-concurrent-downloads '"5"'

Values must be valid JSON. Strings need double quotes inside quotes: '"value"'

Node.js

import { changeGlobalOption } from "@risuko/risuko-js";

await changeGlobalOption({
  dir: "/home/user/downloads",
  "max-concurrent-downloads": "5",
});

Option Reference

General

KeyDefaultDescription
dirOS defaultDefault download directory
max-concurrent-downloads5Maximum active non-torrent download workers. The desktop app can raise this up to 10; the engine uses the value directly and preempts lower-priority non-torrent tasks back to waiting when the queue order requires it
continuetrueResume interrupted downloads
purge-record-on-startfalseWhen the engine starts, drop completed/stopped task records from the session and clear desktop download-history stats. On-disk files for stopped torrent tasks are preserved (the orphan-purge step is told to keep files for those info-hashes); HTTP/FTP/etc. payloads on disk are never touched

Desktop App

These keys are read by the Tauri desktop app. They are stored in user.json and are not part of the engine's JSON-RPC surface.

KeyDefaultDescription
auto-check-updatefalseAutomatically check the Tauri updater endpoint for signed release updates. Desktop-only and opt-in on every platform
last-check-update-time0Last update-check timestamp recorded by the app
legal-acceptedfalseFirst-launch Terms/Privacy acceptance flag; device-local and excluded from cloud sync
clipboard-watchtrue on desktopWatch the clipboard for download links and show a prompt. Not created on Android
clipboard-watch-extensionsarchive, installer, media, document, .torrent, meta4, metalink extensionsHTTP(S) file extensions that trigger the clipboard prompt. Protocol links such as magnet, ED2K, FTP/SFTP, M3U8, and thunder:// do not need an extension match
clipboard-watch-notice-seenfalse on desktopDevice-local flag for the one-time clipboard-watch notice

Connection

KeyDefaultDescription
split16Connections per download (HTTP/HTTPS); ignored when the file is smaller than min-split-size or the server doesn't support Range
min-split-size1MMinimum segment size before the file is split (bytes; accepts K/M/G suffixes)

Speed Limiting

KeyDefaultDescription
max-overall-download-limit0Global download speed limit (bytes/s, 0 = unlimited)
max-overall-upload-limit0Legacy aria2 key. Accepted and persisted but not currently enforced by the engine; the only working upload cap is BitTorrent seeding via bt-upload-rate-limit
max-download-limit0Per-task download speed limit (bytes/s, applies to HTTP, m3u8, and FTP workers)

HTTP

KeyDefaultDescription
user-agentChrome UA stringDefault user agent string
refererDefault HTTP referer
headerDefault HTTP headers (array)
load-cookiesPath to a Netscape/Mozilla format cookies.txt (also accepts curl/wget output) loaded into the per-task cookie jar
netrc-path~/.netrc (%USERPROFILE%\_netrc on Windows)Override the .netrc file used to inject HTTP Basic auth when a URL has no embedded credentials
no-netrcfalseSkip .netrc lookup entirely

Proxy

See the Proxy Support guide for URL schemes, scopes, and bypass syntax.

KeyDefaultDescription
all-proxyHTTP-profile proxy server URL derived from proxy.http. Accepts http://, socks5://, or socks5h://. Used for HTTP/HTTPS, Metalink, HLS, yt-dlp, FTP/FTPS/SFTP, and Usenet when the Download scope is selected
no-proxyBypass list for all-proxy, one entry per line (comma-separated also accepted). Accepts hosts (example.com, matching subdomains too), host:port, IP literals, CIDR ranges (10.0.0.0/8), and * to bypass everything. Matching is case-insensitive; localhost, *.localhost, and loopback addresses are always bypassed. Unparseable entries are dropped
p2p-proxyP2P TCP proxy URL derived from proxy.p2p. Same schemes as all-proxy. Used for BitTorrent TCP peers and HTTP tracker announces, eD2K TCP, Gnutella, G2, and giFT
p2p-no-proxyBypass list for p2p-proxy (same syntax as no-proxy)
p2p-udp-proxyOptional P2P UDP proxy URL. When empty, UDP traffic reuses p2p-proxy. SOCKS5/SOCKS5H is required for DHT, UDP trackers, µTP, and Kad; an HTTP proxy cannot carry UDP
p2p-udp-no-proxyBypass list for p2p-udp-proxy
proxynested objectDesktop/UI preference. Canonical shape is { http: { enable, server, bypass, scope }, p2p: { enable, server, bypass, udp: { server, bypass } } }. The engine reads the flattened keys above

DNS over HTTPS

When enabled, hostnames are resolved by POSTing RFC 8484 wire-format queries (application/dns-message) to a DoH endpoint instead of using the system resolver. A and AAAA records are queried together and the answers cached in memory (smallest record TTL, clamped to 30–3600 s, plus a 5 s negative cache).

This applies to every HTTP client in the engine — downloads, m3u8 segments, RSS, WebDAV/S3 uploads, BitTorrent HTTP trackers, and UPnP. It does not cover BitTorrent UDP trackers/DHT or FTP/SFTP/ED2K/ADC connections, which still resolve through the system. SOCKS5h proxies keep resolving names proxy-side.

KeyDefaultDescription
doh-enablefalseRoute DNS lookups over HTTPS. Only takes effect when doh-url is also set
doh-urlDoH endpoint URL. Must be https:// (e.g. https://cloudflare-dns.com/dns-query)
doh-bootstrapComma/space/newline-separated IPs used to reach the endpoint host without a system-DNS lookup. Entries that don't parse as an IP are dropped. When empty, the endpoint host is resolved via the system resolver
doh-fallbacktrueWhen a DoH query fails (timeout, network error, SERVFAIL), fall back to the system resolver instead of failing the connection
doh-providercloudflareUI-only preference (user.json). The desktop app's provider dropdown (cloudflare, google, quad9, custom); selecting a preset fills doh-url and doh-bootstrap automatically. Not read by the engine

DoH settings are hot-reloaded — changing any doh-* key takes effect on the next connection without an engine restart.

Reliability

KeyDefaultDescription
connect-timeout60Connect timeout in seconds for HTTP/HTTPS/FTP
nzb-body-timeout30Maximum idle time in seconds between chunks while fetching an NZB URL body; applies only to URL-based NZB ingestion
lowest-speed-limit0Stalled-transfer threshold in bytes/s. If the EMA stays below this for lowest-speed-limit-timeout, the worker is aborted (and restarted when auto-retry is enabled). 0 disables the watchdog
lowest-speed-limit-timeout30How many seconds the transfer must stay below lowest-speed-limit before it is considered stalled
uri-selectorfeedbackMirror selection strategy when a task has multiple URIs: feedback (drop slow/failing mirrors), inorder (try left-to-right), or adaptive (prefer fastest)

Low-Speed Auto-Recovery

A separate watchdog from lowest-speed-limit. The renderer's EngineClient samples active task speeds, and any task whose downloadSpeed stays under low-speed-threshold for 5 consecutive polling ticks is force-paused and resumed (with a 30-second per-task cooldown between recovery cycles).

KeyDefaultDescription
auto-detect-low-speed-tasksfalseMaster switch. When false, the recovery loop never runs
low-speed-threshold20Speed threshold in KB/s below which a task counts toward the strike count

Pause/resume only revives a single stalled TCP connection — useful for HTTP/HTTPS, FTP/SFTP, and HTTP-segment streams (m3u8, media/yt-dlp). Peer-swarm protocols (BitTorrent, ED2K, ADC, Gnutella, G2, giFT) are explicitly excluded from this recovery: pause tears down peer connections, aborts in-flight tracker announces and choke negotiations, and the swarm spends minutes warming up again. Tasks whose kind is not in {http, ftp, media, m3u8}, or whose kind is missing, are skipped.

Storage

KeyDefaultDescription
file-allocationfalloc (none on Android)Disk reservation strategy. falloc reserves real blocks via fallocate(2) (Linux) or fcntl(F_PREALLOCATE) (macOS), falling back to set_len. trunc only sets the file length. none lets writes grow the file as needed. The aria2 alias prealloc is accepted as a synonym for falloc
auto-file-renamingtrueWhen the target output file already exists, append .1, .2, … instead of overwriting
remote-timefalseStamp the local file mtime from the server's Last-Modified header on completion (per-task)
use-remote-file-timeUI/global preference mirrored into per-task remote-time when set
m3u8-output-formattsContainer produced after concatenating HLS segments (ts keeps the original transport stream; other values trigger a remux)
file-category-dirsPer-category default directory overrides (object keyed by category id, e.g. { "video": "/downloads/video" }); applied as a fallback when no routing rule matches

BitTorrent

KeyDefaultDescription
keep-seedingfalseSeed until manually stopped (overrides seed-time / seed-ratio)
seed-ratio0Stop seeding at this ratio (0 = no ratio limit)
seed-time0Seed for this many minutes after completing (0 = no time limit)
bt-trackerAdditional tracker URLs (comma-separated)
bt-max-peers-per-torrent100Max concurrent peer connections per torrent (engine restart)
bt-max-outstanding-per-peer0Per-peer pipelined chunk-request cap (engine restart); 0 uses adaptive control starting at 6 and growing up to 96, while an explicit value is capped at 256
bt-upload-rate-limit0Seeding upload rate cap in bytes/s (0 = unlimited) (engine restart)
bt-enable-upnptrueMap the listen port on the router via UPnP IGD (engine restart)
bt-upnp-lease300UPnP mapping lease in seconds (engine restart)
bt-enable-lsdtrueBEP-14 Local Service Discovery via multicast (engine restart)
bt-encryption-policypreferMSE/PE policy: plaintext, prefer, or require (engine restart)
bt-listen-v6falseAlso bind an IPv6 TCP listener on the same port (engine restart)
ed2k-enable-kadtrueEnable client-only eMule Kad source discovery over UDP (engine restart)
ed2k-kad-port4672Local Kad UDP port; must be in 1..=65535 (engine restart)
bt-create-subfoldertrueWhen true, multi-file torrents and magnets are placed under <dir>/<name>/. When false, files are written directly into dir. Single-file torrents are unaffected. Read on each task add (no restart needed); accepted as a per-task option override
bt-save-metadatatrueWhen true and a magnet link is added, the engine resolves the torrent metadata first and writes a synthesized .torrent file to the task's dir before starting the download. Has no effect when adding a .torrent file directly

The DHT (BEP-5) is always enabled and runs as a dual-stack client when an IPv6 socket can be bound. The BitTorrent listener uses an ephemeral port; the legacy aria2 keys listen-port, dht-listen-port, enable-dht, enable-dht6, enable-peer-exchange, and bt-enable-lpd are accepted for backwards compatibility but currently have no effect.

RPC

KeyDefaultDescription
rpc-listen-port16800RPC server port
rpc-host127.0.0.1RPC bind address (set to 0.0.0.0 for LAN access). Also used by the PeerBanHelper listener when that API is enabled
rpc-secretRPC authentication token
pbh-enablefalseStart a second JSON-RPC listener in Aria2Next compatibility mode so PeerBanHelper can monitor and ban BitTorrent peers (engine restart)
pbh-listen-port16801PeerBanHelper RPC port (engine restart). In PeerBanHelper, add an Aria2Next downloader pointed at http://127.0.0.1:<port>/jsonrpc
pbh-rpc-secretToken required as token:<secret> on the PeerBanHelper listener (engine restart)

YouTube (yt-dlp)

KeyDefaultDescription
youtube-formatyt-dlp defaultyt-dlp -f format selector (e.g. bestvideo+bestaudio/best, mp4)

RSS

See the RSS Feeds guide for the full workflow. RSS subscriptions, items, and rules are persisted via the desktop app's storage; the keys below are user-level UI preferences.

KeyDefaultDescription
rss-auto-updateEnable periodic feed polling (boolean; controlled from the RSS panel)
rss-update-intervalPolling interval in minutes between automatic refreshes

Task Routing

See the Task Routing guide.

KeyDefaultDescription
task-routing-rules[]Array of { id, label, pattern, dir, enabled } rules. The first enabled rule whose case-insensitive glob pattern matches the inferred filename wins; dir overrides the download directory and label is exposed as the task tag. Falls through to file-category-dirs then global dir

Completion Scripts

Run a script after every download finishes (success or failure). Per-task overrides are accepted via the desktop app's task options. See the Completion Scripts guide.

KeyDefaultDescription
completion-script-enabledfalseMaster switch. When false, no script runs even if command is set
completion-script-commandAbsolute path to the executable to invoke (no shell parsing)
completion-script-argsWhitespace-tokenised arguments template. Supported placeholders inside any token: {path} (final file path), {hash} (BitTorrent info hash; empty for non-torrent tasks), {status} (complete / error). The same values are also exported as RISUKO_PATH, RISUKO_HASH, RISUKO_STATUS env vars
completion-script-timeout-ms30000Per-invocation timeout in milliseconds. Clamped to 1000300000 (5 minutes). stdout/stderr captured into the log are truncated to 8 KiB

Usenet / NZB

See the Usenet and NZB Downloads guide for the provider setup and recovery workflow. These settings are used for new NZB tasks; task options snapshot the selected profile reference, cleanup policy, and any confirmed archive-limit override.

KeyDefaultDescription
usenet-profiles[]Non-secret provider profile metadata. Each profile has an ID, name, host, port, security mode, enabled state, priority, connection cap, plain-NNTP opt-in, and update timestamp. Usernames and passwords are kept in the OS keychain.
usenet-archive-limitsPlatform defaultsTask-wide archive and PAR2 safety limits. Desktop defaults: 500,000 entries, 2 TiB total expansion, 512 GiB per entry, depth 16, 1000:1 ratio, 10 GiB reserve, 6 active hours. Android defaults: 100,000, 256 GiB, 64 GiB, depth 16, 1000:1, 2 GiB, 2 active hours.
usenet-cleanup-modekeep-allSuccessful cleanup policy: keep-all, delete-par2, or delete-par2-and-volumes. delete-par2-and-archives remains accepted as a legacy alias.
usenet-limits-adjustedfalseSet when a synchronized archive-limit value was invalid or had to be reduced for this device.

Provider profiles use camel-case fields inside the usenet-profiles array:

[
  {
    "id": "primary",
    "name": "Primary provider",
    "host": "news.example.net",
    "port": 563,
    "securityMode": "implicit-tls",
    "enabled": true,
    "priority": 0,
    "maxConnections": 4,
    "allowPlain": false,
    "updatedAt": 1765000000000
  }
]

Valid securityMode values are implicit-tls, starttls, and plain. Plain NNTP also needs allowPlain: true; the app requires a separate user acknowledgement before it saves that state. Lower priority values run first.

The following option keys may be set through risuko.addNzb. The current Add Task form uses the global Usenet archive policy and does not expose per-task archive controls yet:

KeyDescription
usenet-profile-idRestrict the task to one configured provider profile. Omit it to use the enabled provider pool.
usenet-cleanup-modeOverride the global cleanup policy for this task.
usenet-archive-limitsObject with any of maxEntries, maxExpandedBytes, maxEntryBytes, maxNestingDepth, maxCompressionRatio, freeSpaceReserveBytes, and maxActiveSeconds.
usenet-archive-limit-override-confirmedRequired when a per-task override raises an enforced safety limit above its platform default.

Task options must not include a username, password, archive password, or credential-bearing provider object. Risuko removes those values before it saves the task or returns it through RPC.

Saved Credentials

KeyDefaultDescription
saved-credentials[]Non-secret credential profile metadata (id, label, scope, username). Passwords and SSH private keys are stored separately in the OS keychain (risuko-credentials service) and never written to user.json

Legacy P2P / IPC stacks

KeyDefaultDescription
adc-hubDefault ADC / DC hub URI (adc(s)://, dchub://, nmdc://) used as a hint when a file URI doesn't include one
adc-nickNickname presented to the ADC / DC hub
gnutella-cacheGWebCache URLs (comma-separated) used to bootstrap Gnutella ultrapeers
g2-cacheBootstrap caches for the Gnutella2 (G2) network
gift-enabledfalseAllow gift:// URIs to be forwarded to a local giftd daemon
gift-host127.0.0.1giFT IPC bind address
gift-port1213giFT IPC port

External Engine

By default the desktop app boots an embedded engine in-process. Switch to External Engine mode to point the UI at a separately running risuko serve (or any aria2-compatible RPC server). When enabled, the embedded engine is not started; all add_uri, polling, and config writes are routed over JSON-RPC.

KeyDefaultDescription
external-engine-enabledfalseSkip the embedded engine and connect to a remote RPC server instead
external-engine-hostHostname or IP of the remote RPC server
external-engine-port16800Port of the remote RPC server
external-engine-secretToken to send as token:<secret> on each call

Logging

KeyDefaultDescription
log-dir-override""Override the directory where rolling log files are written. Must be an absolute path to a writable directory. When empty (the default), logs go to the OS-specific app log directory. Useful on Android to redirect logs to a publicly accessible path
log-levelwarnVerbosity of the tracing subscriber. One of error, warn, info, debug, trace (these are tracing_subscriber::EnvFilter directives). Takes effect only after an app restart, because the subscriber is initialised once at startup

Startup-only Keys

The following keys are read once when the engine starts. Changing them at runtime is accepted (the value is persisted) but does not take effect until the engine is restarted (Quit & relaunch the desktop app, or restart risuko serve):

dht-listen-port, ed2k-enable-kad, ed2k-kad-port, ed2k-port, listen-port, rpc-listen-port, rpc-secret, pbh-enable, pbh-listen-port, pbh-rpc-secret, bt-max-peers-per-torrent, bt-max-outstanding-per-peer, bt-upload-rate-limit, bt-enable-upnp, bt-upnp-lease, bt-enable-lsd, bt-encryption-policy, bt-listen-v6.

All other keys are hot-reloaded on the next task or polling cycle.

On this page