Skip to content

barline

A code-first DAW. Songs are TypeScript. The timeline, beat grid, and piano roll are live projections of your code — and an MCP-connected AI edits the song and hears the result.

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.