strudex
v0.1.0
Published
Strudel live-coding from your terminal — nvim bridge, TUI punchcard, and full autocomplete
Downloads
127
Maintainers
Readme
strudex
Live-code Strudel from your editor and terminal.
Strudel's web REPL is great, but if you live in nvim you want your own editor, your own keybindings, and something to look at that isn't a browser tab. strudex keeps the browser purely as an audio engine and moves everything else into the terminal.
strudex play try.js # bridge + browser, hot-reloads on save
strudex punch try.js # scrolling punchcard in the terminalWhat you get
- A bridge. Serves a headless-ish Strudel page and re-evaluates your patch every time you save. The browser is only ever an audio device.
- A terminal punchcard. Notes scroll past a fixed playhead, driven by the browser's real transport clock. Overview mode shows only the pitches your patch actually plays; press enter for the full chromatic piano roll.
- Neovim integration. Eval the buffer, stop, play/pause, and mute/solo individual blocks without leaving the file.
- Autocomplete. A generated
strudel.d.tscovering 797 methods with inline docs, so.lpf(and.bank(complete in any LSP-backed editor. - Media keys. The play/pause key on your keyboard toggles playback.
Requires
Bun and a browser. Bun runs the audio bridge and the punchcard renderer; the CLI itself runs on Node 18+.
curl -fsSL https://bun.sh/install | bashInstall
npm install -g strudex
strudex init ~/patchesThen add the optional extras — shell aliases and the nvim plugin:
strudex setup shell >> ~/.zshrc # sx / stp aliases
strudex setup nvim # the nvim pluginFrom source
git clone https://github.com/charlietlamb/strudex
cd strudex
./install.shThe installer links the binary into ~/.local/bin, then asks before it
touches your shell rc or your nvim config. Nothing is written without a yes,
and your rc file is backed up first.
Manual install, if you'd rather:
bun install
ln -s "$PWD/bin/strudex.mjs" ~/.local/bin/strudex
strudex setup shell >> ~/.zshrc # optional: sx / stp aliases
strudex setup nvim # optional: the nvim pluginStart a patch directory
strudex init ~/patches
export STRUDEX_HOME="$HOME/patches"
strudex play try.jsinit scaffolds an example patch plus types/strudel.d.ts and a jsconfig.json,
which is what makes autocomplete work. Run strudex types in an existing
directory to add them to a project you already have.
Once STRUDEX_HOME is set, a bare filename resolves from anywhere:
strudex play try.js finds it no matter which directory you're in.
Writing patches
A patch is ordinary Strudel, with one convention: top-level name: labels mark
independent blocks.
setcpm(90 / 4);
bassline: note("<c2 g#1>").sound("supersaw").lpf(400);
kick: s("bd*4").postgain(0.7);
_hats: s("hh*8").gain(0.4);A _ prefix mutes a block. The nvim plugin toggles that prefix for you, so
mute and solo are just edits to the file — no hidden state, and the patch is
always exactly what you hear.
Commands
| | |
|---|---|
| strudex play [patch] | start the bridge, open the browser, watch for saves |
| strudex punch [patch] | terminal punchcard |
| strudex init [dir] | scaffold a patch directory |
| strudex types [dir] | add strudel.d.ts + jsconfig.json to a directory |
| strudex setup shell | print the shell functions |
| strudex setup nvim | install the nvim plugin |
| strudex stop | kill a running bridge |
-p / --port overrides the port (default 4321, or $STRUDEX_PORT).
--no-open starts the bridge without launching a browser.
Punchcard keys
| | |
|---|---|
| enter / esc | zoom into the full piano roll / back to overview |
| j k, arrows | scroll |
| ctrl-u / ctrl-d | half page up / down |
| g / G | top / bottom |
| q | quit |
The mouse wheel scrolls too. The playhead only moves when a browser is actually playing — the punchcard reads the transport clock over HTTP rather than guessing at it.
Neovim
| | |
|---|---|
| <C-CR> or <leader>me | eval buffer |
| <leader>ms | stop |
| <leader>mp | play / pause |
| <leader>mm | mute / unmute block under cursor |
| <leader>mo | solo block under cursor |
| <leader>mM / <leader>mU | mute / unmute all |
The plugin attaches to any .js file under $STRUDEX_HOME. If that isn't set
it falls back to anything under a strudex/ or strudex-patches/ directory,
plus *.strudex.js. Override with vim.g.strudex_patterns.
Offline
Everything except the initial bun install runs locally. The bundled Strudel
REPL is served from disk. Default drum samples stream from Strudel's CDN on
first use, so if you want to work fully offline, point at a local sample
directory with samples('...') in your patch.
Autocomplete
types/strudel.d.ts is generated from the published Strudel sources rather
than hand-written, so it stays honest:
bun run typesIt declares interface String extends Pattern, which is what makes
"bd*4".fast(2) type-check — mini-notation strings really are patterns at
runtime, because miniAllStrings() patches String.prototype.
Tests
bun test # unit + patch checks + nvim plugin
node test/test-clock.mjs # end-to-end, needs playwrightThe clock test drives a real Chromium with autoplay forced on and walks the
whole chain — browser scheduler → websocket → bridge → GET /clock →
punchcard — to prove the playhead actually moves.
Licence
MIT. Strudel itself is AGPL-3.0 and is not vendored here; bun install
fetches it from npm.
