onbgm github ↗

background music, written note by note by ai agents.

An agent writes a plain-text score: sections, chords, melodies, drum patterns. onbgm arranges, performs, mixes and renders it into a finished instrumental track. Every note stays readable, every edit stays local, and the same score always sounds the same.

$pip install onbgm
written-in-text.yaml · the real score49 lines

written in text

40 s · f major · 96 bpm · written by an agent with onbgm

0:00.0 bar 01 · intro
melody chords bass drums

Press play. The score on the left is the exact file the music was rendered from: the bar being played lights up in the melody, and the section underline follows the arrangement. On the right, every note is drawn as the shape of its instrument.

listen

Six tracks, each composed end to end by a Claude agent with onbgm: it read the docs, wrote the score, rendered drafts, read the loudness and balance report, and revised. A second agent reviewed every score before it was accepted.

how it works

The agent describes what the music should do. onbgm decides how it is performed: velocity, pedaling, voice leading, micro-timing, the mix and the master.

1

the agent writes a score

Sections with energy curves, chords per bar, melodies note by note. Plain YAML, so it can be read, diffed and reviewed.

meta: {bpm: 84, key: "A minor", loop: true}
sections:
  - {name: intro, bars: 4, energy: 0.3}
  - {name: theme, bars: 8, energy: "0.5->0.8"}
harmony:
  intro: "Am | F | C | G"
  theme: "Am | F | C | G | Dm | F | Esus4 | E"
tracks:
  keys: {sound: epiano, texture: comp}
  lead:
    sound: vibraphone
    notes:
      theme: "E5/4. D5/8 C5/4 A4/4 | …"
2

onbgm performs and mixes it

Every command answers in JSON, and the render report tells the agent whether loudness follows the energy curve and how the parts balance.

$ onbgm render score.yaml --json
{
  "ok": true,
  "duration_s": 40.5,
  "lufs": -14.8,
  "timeline": {
    "bpm": 96.0, "key": "F major", "bars": 15,
    "sections": [
      {"name": "intro", "start_s": 0.0},
      {"name": "build", "start_s": 5.0},
      {"name": "groove", "start_s": 10.0},
      {"name": "theme", "start_s": 15.0},
      {"name": "end",   "start_s": 35.0}
      …
3

you edit by conversation

“bring the climax in 4 bars earlier, and switch the bass to pizzicato.”

-  - { name: build,  bars: 8, energy: 0.4->0.85 }
+  - { name: build,  bars: 4, energy: 0.4->0.85 }
-  build:  "Dm9 | Bbmaj7 | Fmaj7 | C | Gm9 | …"
+  build:  "Dm9 | Bbmaj7 | Gm7 | A7sus4 A7"
-    sound: contrabass
-    texture: bass-sustain
+    sound: pizzicato
+    texture: bass-pizz

Those lines change. Every other section renders identically, note for note.

at: "0:15"

exact timing

Section starts, the climax at 0:42, loop points and cut points are exact, never approximate.

bars: 8 → 4

local edits

Change four bars and only those four bars change. The rest stays bit-identical.

seed: 0

reproducible

The same score always renders to the same audio, on any machine.

sound: vibraphone

no vocals

Built for background music: videos, games, podcasts and apps.

the film

Our launch film. An agent wrote its soundtrack with onbgm, and you can watch the score being written while you hear it.

45 seconds, 1920 × 1080. Each instrument enters on the bar after its block is written, and the melody bar that is playing lights up in the score.

The timing came first. onbgm fit turned the film's cut points into a tempo and a set of sections, so the riser and the final impact were scheduled on the score's own timeline and land exactly on the cut to the end card.

install

onbgm is open source under the MIT license. It runs on macOS and Linux with Python 3.10 or newer, and FluidSynth for the General MIDI fallback.

terminal
brew install fluid-synth        # debian/ubuntu: sudo apt install fluidsynth
pip install onbgm               # or: uv tool install onbgm
onbgm fetch                     # sound libraries, about 1.7 GB
onbgm doctor                    # check the setup

onbgm init my_bgm --example late_study
onbgm render my_bgm/score.yaml -o my_bgm/out/v1
onbgm review my_bgm/out/v1      # listen in the browser and leave comments

for agents

  • The agent docs are a skill: workflow, score format, CLI and arranging recipes. skills/onbgm ↗
  • Every command takes --json. Errors name the location, the reason and the fix.
  • Sounds come from free and CC0 sample libraries, pinned to exact versions. credits ↗

a free library of tracks is in production.

Instrumental tracks written by agents with onbgm, each with its score and rich metadata. Search them here, or let your agent search them for you.

scenemoodtempolengthclimax timeseamless loop