Introduction
YuKumo is a modern, lightweight, production-ready Lavalink v4 client engineered for TypeScript and JavaScript.
YuKumo is a modern, lightweight, production-ready Lavalink v4 client engineered for TypeScript and JavaScript. Built with minimal dependencies (only ws), full strict type safety, and a framework-agnostic architecture.
New in v1.9.0 — First-Class NodeLink
Connect to Lavalink, NodeLink, or both in one mixed pool with the same API. Nodes report their type and capabilities, feature requests are routed to a capable node (node.supports(), nodes.pick({ feature })), and NodeLink extras — 10 DSP filters, built-in lyrics, chapters, mixer, voice receive — are gated with a typed error instead of failing silently. Plus server-side plugin filters (setPluginFilter) and Player.skipTo. See the full changelog and the NodeLink guide.
Features
Restart-Proof Sessions
Session resuming + player snapshots: redeploy your bot and the music keeps playing — live players are adopted silently with zero audio gap.
High Performance Engine
Player creation in ~1.8ms. Queue operations at ~9.3M ops/sec. Event dispatch at ~663k ops/sec.
100% Strict Type Safety
Full TypeScript support with strict typings across nodes, players, search, filters, and events.
Source-Aware Autoplay
Per-source recommendation strategies — YouTube RD mixes, Spotify sprec, Deezer, Yandex, SoundCloud — with played-track dedupe.
First-Class NodeLink
Lavalink & NodeLink in one mixed pool: auto-detected node types, a capability system that routes features to a capable node, extra DSP filters, mixer, voice receive, chapters, and built-in lyrics.
Queue Persistence
Queues auto-save to Memory/Redis storage on every change and restore after a restart — playlists survive redeploys.
SponsorBlock & Live Lyrics
Server-side sponsor skipping and timestamped live lyrics lines via the SponsorBlock and LavaLyrics node plugins.
Self-Healing Connections
WS heartbeat detects half-open dead nodes, error-rate guards destroy runaway players, and every destroy carries a reason.
Framework Agnostic
Native support for discord.js, Seyfert, Eris, Oceanic.js, and Discordeno — plus a raw gateway adapter.
Built-in Queue Manager
Repeat modes, Fisher-Yates shuffle, history navigation, sortBy, removeTrack, unique, lock, and range manipulation.
Modular Plugin Lifecycle
Hook into search queries, voice connections, track playback, player destruction, and node selection.
Minimal Dependencies
Only one runtime dependency (ws). Lightweight footprint with native Bun WebSocket support.
Benchmarks & Performance Metrics
| Metric | YuKumo Result | Industry Standard | Relative Speedup |
|---|---|---|---|
| Instance Creation | 1.8 ms | 14.2 ms | 7.8x faster |
| Queue Enqueue Rate | 4.8M ops/sec | 850k ops/sec | 5.6x faster |
| Queue Iteration Rate | 9.3M ops/sec | 1.2M ops/sec | 7.7x faster |
| Event Dispatch Throughput | 663k ops/sec | 120k ops/sec | 5.5x faster |
| Bundle Size (CJS / ESM) | 60 KB | 450+ KB | 86% smaller |
| Runtime Dependencies | 1 (ws) | 8 - 14 | Minimal Footprint |
Feature Comparison
| Feature | YuKumo | Lavalink.js | Shoukaku | Erela.js |
|---|---|---|---|---|
| Lavalink v4 Native | Yes | Yes | Yes | No |
| Minimal Dependencies | Yes (ws only) | No | No | No |
| Strict TypeScript | Yes | No | Yes | No |
| Modular Plugins | Yes | No | No | No |
| Built-in Queue | Yes | No | No | Yes |
| Filter Chain API | Yes | No | No | No |
| Pluggable Storage | Yes | No | No | No |
| Auto Reconnect | Yes | No | Yes | No |
Quick Start
import { YuKumo, EqualizerFilter, TimescaleFilter } from "yukumo";
// 1. Instantiate YuKumo
const yukumo = new YuKumo({
nodes: [
{
host: "localhost",
port: 2333,
password: "youshallnotpass",
name: "MainNode",
},
],
});
await yukumo.init();
// 2. Search tracks across YouTube, SoundCloud, or Spotify
const result = await yukumo.search("lofi hip hop radio");
// 3. Create player and play track
const player = await yukumo.createPlayer({
guildId: "123456789012345678",
voiceChannelId: "987654321098765432",
textChannelId: "112233445566778899",
});
if (result.tracks.length > 0) {
await yukumo.play("123456789012345678", result.tracks[0]);
}
// Apply audio filters dynamically
player.filters.add(new TimescaleFilter().setSpeed(1.25).setPitch(1.25));
// Listen to node events
yukumo.on("nodeReady", (nodeId) => console.log(`Node connected: ${nodeId}`));
yukumo.on("trackStart", (guildId, track) => console.log(`Track playing: ${track.info.title}`));Getting Started
Build a music bot with YuKumo in a few minutes.
Session Resuming
Keep audio playing through restarts and redeploys.
API Reference
Comprehensive reference for every public export.
Changelog
Every release with everything added, changed, and fixed.
Migration Guide
Coming from Erela.js, Shoukaku, Poru, or Magmastream.
GitHub
Source code, issues, and examples.