It's real TypeScript
Imports, classes, loops, third-party npm packages. Pattern is a
three-member interface — your own class is as first-class as r or
euclidean.
A song in barline is not a project file — it is a TypeScript program that
imports @barline/core. for, if, classes, and your own helpers all work.
The library gives you pattern primitives and a runtime; you bring the
composition.
import { r, at, backbeat, notes, beats, bars, fx } from "@barline/core";import type { Song } from "@barline/runtime";
export default function (song: Song) { const kick = song.track({ name: "kick", output: { kind: "synth", synth: { id: "kick" } }, effects: [fx.distortion({ drive: 0.35, wet: 0.6 }), fx.limiter({ threshold: -2 })], }); const hats = song.track({ name: "hats", output: { kind: "synth", synth: { id: "hat", params: { volume: -12 } } }, }); const rumble = song.track({ name: "rumble", output: { kind: "synth", synth: { id: "bass", params: { volume: -6 } } }, effects: [fx.sidechain({ source: "kick", amount: 0.8 })], // the pump });
// INTRO — a filtered heartbeat. Edit while it plays; changes land next bar. song.section("intro", bars(16), () => { kick.play(r`x . . . x . . . x . . . x . . .`).gain(0.9); hats.play(at([2, 6, 10, 14])).gain(0.7); rumble.play(notes(["F1", null, "F1", "Ab1"], beats(0.5))).gain(0.5); });
song.arrange([{ section: "intro" }]);}Type that, press play, and a 148 BPM techno loop comes out of the browser. Drag a note in the piano roll and the code updates. Ask Claude to make the drop harder and it edits the same document you are editing. Nothing is config.
It's real TypeScript
Imports, classes, loops, third-party npm packages. Pattern is a
three-member interface — your own class is as first-class as r or
euclidean.
Code is the source of truth
Timeline, beat grid, and piano roll are projections of the AST, never independent state. Edit either side; both update.
Performance is flags, not fast typing
MIDI pads and knobs bind to typed flags. Section code branches on them. The controller is the performance surface; the code is the composition.
The AI hears the output
An MCP-connected model edits the song structurally and reads a live audio-feature stream: change → render → listen → iterate.