Lunacord

Introduction

Builder-first Lavalink v4 client for Bun and Node.js, shipped as a family of @lunacord/* packages.

What is Lunacord?

Lunacord is a music layer for Discord bots. It talks to a Lavalink v4 server, manages nodes, players, queues, filters, and lyrics, and ships a batteries-included discord.js integration so the average music bot ends up being about 15 lines of code.

The packages

  • @lunacord/core — the Lavalink manager (Lunacord), nodes, players, queue, filter builder, cache, persistence interface, plugin runtime, errors, Zod schemas.
  • @lunacord/discordjsMusicKit: auto-wires raw packet forwarding, op:4 voice sends, intent validation, userId / numShards binding, a default 18-command slash pack, middleware, and embed factory.
  • @lunacord/pluginsPluginBuilder, PluginManager, and builtins: logger, metrics, debug, autoplay, stats reporter.
  • @lunacord/lyricsLyricsClient with Lyrics.ovh and Genius providers (plus a Genius OAuth helper).
  • @lunacord/cache-redisRedisCacheStore and RedisPersistenceAdapter.
  • lunacord.js (npm) — umbrella package: re-exports the libraries above, optional subpaths (/plugins, /lyrics, /cache), and createLunacordMusicClient() for a ready-made Client + MusicKit.

Why builder-first?

Every public API has an explicit, fluent builder:

import { Lunacord } from "@lunacord/core";

const lunacord = Lunacord.create()
  .userId("bot-id")
  .shards(1)
  .node({ id: "main", host: "localhost", port: 2333, password: "..." })
  .nodeSelection.leastLoaded()
  .resume(true)
  .build();

Type-state builders make impossible states unrepresentable at compile time (you can't call .register() on a NodeBuilder until setHost, setPort, and setPassword have been called).

Three ways to use Lunacord

  1. Core first — follow the Quickstart: Lunacord.create(), gateway forwarding, bindIdentity, players, and searchAndPlay.
  2. Batteries-included — use MusicKit; see the MusicKit Quickstart for a bot in a few lines with the default slash pack.
  3. Custom plugins / providers — compose your own via the plugin and persistence interfaces.

On this page