← All pages
Write it

The score format

What Claude writes is a score in this format, and what the app plays is the same file. It is JSON so an agent can write it, and precise enough that a bar that does not add up is caught before it is kept.

ode-to-joy.score.json
{
  "formatVersion": 1,
  "metadata": {"id": "ode-to-joy", "title": "Ode to Joy", "composer": "Ludwig van Beethoven", "level": "beginner", "difficulty": 1},
  "timing": {"ticksPerQuarter": 480, "tempo": [{"tick": 0, "microsecondsPerQuarter": 600000}]},
  "notes": [
    {"id": "m1-1", "pitch": 64, "start": 0, "duration": 450, "velocity": 80, "part": "melody", "hand": "right"},
    {"id": "m1-2", "pitch": 64, "start": 480, "duration": 450, "velocity": 74, "part": "melody", "hand": "right"},
    {"id": "m1-3", "pitch": 65, "start": 960, "duration": 450, "velocity": 74, "part": "melody", "hand": "right"},
    …
  ]
}
The head of a score the app ships, cut to its first notes of 102, when this page was built.

What a score holds

  • ✓Metadata: a title, the composer, a level and a difficulty from 1 to 10, tags, and where it came from under which licence.
  • ✓Timing: ticks per quarter, a tempo map and the time signatures.
  • ✓Notes: pitch, start and duration in ticks, velocity, and the part, hand, voice and finger.
  • ✓Parts, sections by name, pedals and dynamics.
  • ✓An arrangement per level, as a change to one set of notes rather than a copy of it.

One owner

The format is defined once, in packages/score-format, and a repository check refuses a second copy anywhere else. The JSON Schema is generated from that definition, and MIDI and MusicXML are read by the same package.