Skip to content

tonal_py

A pragmatic Python port of the tonal JavaScript music theory library — version 6.4.3, with 23 namespaces covering notes, intervals, chords, scales, keys, modes, voicings, rhythm patterns, and more.

from tonal_py import Note, Chord, Scale, Key

Note.midi("C4")              # 60
Chord.get("Cmaj7").notes     # ('C', 'E', 'G', 'B')
Scale.get("C major").notes   # ('C', 'D', 'E', 'F', 'G', 'A', 'B')
Key.major_key("C").chords    # ('Cmaj7', 'Dm7', 'Em7', 'Fmaj7', 'G7', 'Am7', 'Bm7b5')

Why tonal_py

  • Behavior parity with tonal.js. The data tables (106 chord types, 92 scale types, 7 modes, 4 key scales) are transcribed verbatim and verified row-by-row against the JS implementation. If tonal returns a value, so do we.
  • Pythonic at the surface, faithful underneath. Function names use snake_case (Note.from_midi, not Note.fromMidi); types are frozen dataclasses; nothing depends on a JS runtime.
  • Zero runtime dependencies. Same ethos as upstream tonal.

Install

uv add tonal-py
# or
pip install tonal-py

Requires Python 3.13+.

What's next

  • Getting Started — a 5-minute tour of the most common operations (notes, chords, scales, transposition).
  • Concepts — how tonal models pitch, why notes have coordinates, what a "pitch class set" is.
  • API Reference — every function in every namespace, generated from the source.
  • Naming Conventions — exact tonal.js → tonal_py identifier mapping for porting JS code.

Status

All 7 phases of the port are complete. 514 tests pass, including per-row checks for every chord and scale type against the JS oracle.