jevstrudel
Strudel — the JavaScript port of TidalCycles — with two
additions: an MCP bridge so Claude can play and edit code in a browser
session, and the jev panel on the REPL's left, which holds everything this
fork adds (the song browser, who is listening, your account, how to
connect your AI, and everything the site stores, for anyone to read) so it
is never mistaken for Strudel's own, and Jev at
work in a pane under the editor. The
songs live here too: pick one and it opens there with its spec, its code
loads, and it plays from the top. The public site also hosts an MCP for everyone's own
AI (/ai/, worker/README.md, The hosted MCP): signed in, a visitor
connects Claude Code or Claude, which plays into their own tab's sandbox
and publishes songs Jev screens.
What this repo is made of
It is a fork, kept as three layers so each can be updated on its own:
| Branch | What it is |
|---|---|
strudel-upstream | Strudel's main, from codeberg.org/uzu/strudel (remote strudel) |
strudel-llm | The MCP fork as published, calvinw/strudel-llm-mirror (remote strudel-llm) |
strudel-llm-rebased | The fork's 9 commits rebased onto strudel-upstream |
jevstrudel | strudel-llm-rebased plus this project: the songs, samples, vocal tools, the flake, and the song browser |
Both remotes have push disabled; this repo only ever reads from them.
Running it
buck2 run //:dev, inside the devshell (nix develop, or direnv), is the
working tree with hot reload on http://localhost:4322/: edit the site, a
song or a sample and the page updates. Beside it runs the jevstrudel Worker
(worker/) with the Jev relay and an MCP hub: .mcp.json runs
nix run .#mcp, a small stdio proxy, so Claude can play code into an open
tab. Either side can restart without the other. The proxy's
use_environment tool switches it to the public site's hosted MCP, signed
in as you with a passkey, and back (tools/mcp/).
buck2 run //:preview is the last listen before a deploy: the deploy's own
static build with the production Worker (the relay, no MCP) on
http://localhost:4324/.
buck2 run //:check-songs plays every song fast in a silent headless tab
on the dev server and reports what Jev did, and anything that failed.
nix flake check evaluates every song in Node against a stand-in Jev.
nix build .#static is the site alone, for any static host: the REPL and
song browser with the sample pack bundled, and no MCP. nix run .#deploy
publishes it with the Jev relay as a public Cloudflare Worker at
https://jevstrudel.deizel.workers.dev; the Cloudflare token comes from
1Password on each run.
The devshell also has speak TEXT OUT.wav and vocode IN.wav OUT.wav --chord "a2 a3 c4 e4" (a Windows speech voice, and a vocoder that makes a
chord sing it), and ffmpeg for cutting vocal clips.
Audio comes out of the browser (on Windows), so nothing in WSL needs a sound server.
Layout
Everything upstream (packages/, website/, …) is Strudel's, with the
MCP fork's changes on top. This project adds:
songs/<theme>/<song>/— one folder per song:SPEC.mdandsong.js.samples/<sound>/— the sample pack: every folder is a sound (samples/jeff/jeff.mp3plays ass("jeff")). Songs load it withsamples('jev-samples/strudel.json'), which the site builds.tools/vocals/— the vocal tools' sources;tools/mcp/— the MCP proxy;tools/measure/— each song's mix, measured;tools/events/— the Worker's telemetry, read back;tools/jev-history/— Jev's decision history per song, from the stored performances;tools/worktree-samples/— a worktree's own samples in the headless tools.website/src/jev/— the song browser,jev()(TypeSafe's API as Strudel patterns) and link previews.worker/— the Cloudflare Worker: the Jev relay, and the MCP hub in dev.nix/,flake.nix— how jevstrudel is built and run.BUCK,.buckconfig,toolchains/,tools/dev/,tools/check-songs/— the//:dev,//:previewand//:check-songstargets.