npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

beats-radio

v0.2.1

Published

Agent-composed Strudel radio: a bun server + prebuilt browser player you run with `bunx beats-radio start`.

Readme

beats-radio

I spent some time teaching Claude to write music in Javascript and inadvertently recreated this meme.

Watch an example

TODO: add

(or visit my radio)

Why did you make this?

My thought process:

  1. I wonder if Claude can write music?
  2. Ok, it’s not an audio model, but surely there’s a music coding library? LLMs love writing code. Yes, I know that Suno exists...
  3. Strudel looks good, let’s try that!
  4. Ok, some other people have tried that too
  5. How can it write good songs if it can’t hear them?
  6. Hmm alright let’s teach it some rules of style
  7. Back to #4, I don’t actually know that much music theory
  8. Ok, now we’re getting somewhere
  9. Ah, there’s a /radio skill now in Claude Code
  10. That just opens YouTube, lame. Let the agents create!
  11. Let's make this into an agent-driven radio
  12. (Fable gets released) it should have Winamp style visualisations too, right?
  13. Here we are :sparkle:

It also turns out Claude loves writing Chromatics-inspired italodisco and Ethiopian jazz. Who knew?

How does this work?

Your coding agent composes full, arranged songs in Strudel (a live-coding music language); a browser player (the 'radio') streams the shared queue with the real Web Audio engine

The /beats skill writes a song based on a theme (yours or your agents), and you can work collaboratively with your agent to give feedback, tweak or rewrite each song

Get started

Requires bun ≥ 1.2.

To have an agent compose for the radio, install the beats skill to drive the beats-radio CLI. Two ways:

Any SKILL.md-aware agent (Claude Code, Codex, …):

bunx beats-radio install-skill

This copies skills/beats into the agent homes it finds (~/.claude/skills, ~/.codex/skills); pass --target <dir> to install elsewhere.

Claude Code plugin:

/plugin marketplace add morganjbruce/beats-radio
/plugin install beats@funkmaster

And you then can compose with:

/beats <theme>

The skill will open http://localhost:3001: click ▶ Start radio once to unlock browser audio.

Usage

  • Themes/beats midnight city pop, /beats something like Boards of Canada, or just /beats and let it choose. The agent plans, writes, validates, and iterates on a full arranged song (real structure and an arc, not a 4-bar loop), then posts it to the queue.

  • The queue — songs stream to every open player tab over SSE and advance on the cycle boundary. Each song has a permalink and shows its generation provenance; you can delete songs from the player.

  • Evolving radio - /loop 3m /beats <your theme> to generate songs on an ongoing basis

  • Team / remote radio — point your agent and the CLI at a shared deployment by putting BEATS_SERVER and BEATS_TOKEN in ~/.beats/env:

    BEATS_SERVER=https://your-radio.example.com
    BEATS_TOKEN=your-secret-token

    Then bunx beats-radio post <artifact> --remote (or ask your agent for the remote radio).

Development

Working in a checkout of this repo:

bun install
bun run dev

dev runs Vite (player on http://localhost:5173) + a watched server (:3001) concurrently.

The repo dogfoods its own skill: .claude/skills/beats symlinks to skills/beats, so /beats here uses the same skill that ships in the package.

Deploy your own public radio

The appliance runs anywhere bun does. The repo includes a Dockerfile and fly.toml for fly.io:

fly launch --no-deploy                          # create the app (keep the bundled fly.toml)
fly volumes create beats_data --size 1 --region lhr   # persistent state for history.db + songs
fly secrets set BEATS_TOKEN=<token>             # required to post to the public radio
fly deploy

Notes:

  • The volume mounts at /app/.beats (the server's cwd-relative default), so history and posted songs survive redeploys.
  • Keep auto_stop_machines = "off" with min_machines_running = 1: the radio holds open SSE streams, so the machine must stay up for the queue and listeners to survive idle periods.
  • Once deployed, listeners just open the app URL; composers point ~/.beats/env at it (see Usage above).

Share it with your friends, send songs from each other's agents!

CLI reference

| Command | What it does | | --- | --- | | start [--port N] [--open] | Start the server + built-in player on :3001 (--open launches a browser) | | stop | Stop a radio started with start (reads the pid file in the state dir) | | validate <artifact.mjs> | Statically check a song artifact (regex + syntax) before it plays | | post <artifact.mjs> [--remote] | Post a song to the running radio; --remote uses ~/.beats/env | | sounds | Print the authoritative prebaked-sound inventory as JSON | | install-skill [--target <dir>] | Copy the beats skill into ~/.agents/skills (the universal dir) plus ~/.claude/skills / ~/.codex/skills where present (or --target) | | version | Print the version |

What would make this better?

  • A real critique loop. Claude can’t process audio, so we could feed it through a model that can, like Gemini. But I wanted something that was only dependent on one agent harness, so we just have structural validation & a bunch of rules to follow... which mostly works, but sometimes you get slop
  • Build a corpus of generated songs that meet human preference, and use those as examples for Claude of good/bad songwriting.
  • It’s probably overfitted on verse-chorus-verse-chorus-bridge songs, because I got sick of little loops

Huge appreciation for:

  • This excellent project, from which I cribbed a bunch of my initial prompting (particularly around harmony & music theory)
  • The folks behind Strudel, tidecycle and the many, many giants that this is standing on :)

See also:

Thanks, I hate it

  • It’s not a replacement for human creativity and genius, I built this to satisfy my curiousity!
  • Best to think of these as rough prototypes, not real songs
  • Fable/Opus love using every cliche in the book, but sometimes, they generate something that’s (at the very least) memorable, and sometimes genuinely touching
  • You probably shouldn't read the code too closely, this is the repo where I let the agents run wild