npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@toyrobot/chord-theory

v1.0.0

Published

Music theory engine with borrowed chords, reverse diatonic lookup, and intelligent chord symbol generation — the algorithms that tonal and teoria don't have

Readme

@toyrobot/chord-theory

Music theory engine with the algorithms that tonal and teoria don't have.

Zero dependencies. Pure TypeScript. Works everywhere.

What this does that nothing else does

| Feature | chord-theory | tonal | teoria | |---------|:---:|:---:|:---:| | Borrowed chords (modal interchange) | Yes | No | No | | Reverse diatonic lookup | Yes | No | No | | Intelligent partial voicing naming | Yes | No | No | | Chord parser with 30+ notation aliases | Yes | Yes | Yes | | 4 heptatonic scale systems | Yes | Partial | Partial | | MIDI voicing generation | Yes | No | Yes |

Borrowed Chords

"What chords can I borrow in C major?" — answered with one function call. Searches natural minor, harmonic minor, and melodic minor for chords that don't exist in your current system. Deduplicates by pitch+type, sorts by chromatic distance. No other library does this.

Reverse Diatonic Lookup

"I like the sound of Ebmaj7 — where does it live?" — searches all 4 scale systems across all 12 keys to find every diatonic context where a chord naturally occurs. Returns Roman numerals with key and system context. Work backwards from sound to theory.

Intelligent Chord Symbol Generation

Takes a chord and a set of active intervals, generates the correct symbol for partial voicings. Missing the 3rd? It knows that's a sus chord. Have a 9th but no 7th? That's an add9. Non-consecutive extensions get proper (add) notation. 20+ edge cases handled.

Install

npm install @toyrobot/chord-theory

Quick Start

import {
  getBorrowedChords,
  findDiatonicMatches,
  findMatchesForSymbol,
  parseChord,
  chordSymbol,
  buildChordInfo,
} from '@toyrobot/chord-theory';

Borrowed Chords

// What chords can I borrow in C major?
const borrowed = getBorrowedChords(0, 'major');

borrowed.forEach(b => {
  console.log(`${b.chord.name} — from ${b.sourceLabel}`);
});
// Cm7 — from Natural Minor
// C°7 — from Harmonic Minor
// Dbmaj7 — from Harmonic Minor
// Dm7 — from Melodic Minor (wait, that's diatonic... no, this is the m(maj7) variant)
// ...every borrowable chord, sorted by distance

Reverse Lookup

// Where does Dm7b5 naturally occur?
const matches = findDiatonicMatches(2, 'hdim7');

matches.forEach(m => {
  console.log(`${m.numeral} in ${m.key} ${m.systemLabel}`);
});
// vii° in Eb Major
// ii° in C Natural Minor
// ii° in C Harmonic Minor
// vi° in F Melodic Minor
// vii° in Eb Melodic Minor

// Or use the convenience wrapper with a chord symbol string:
findMatchesForSymbol('Ebmaj7');
// [{ numeral: 'I', key: 'Eb', system: 'major', ... }, ...]

Parse Chord Symbols

// Handles sharps, flats, Unicode, slash chords, beat durations
parseChord('C#m7b5');    // { root: 1, qualityKey: 'hdim7', ... }
parseChord('Bb7/F');     // { root: 10, qualityKey: 'dom7', bass: 5, ... }
parseChord('Am(8)');     // { root: 9, qualityKey: 'min', beats: 8, ... }
parseChord('Δ7');        // { root: 0, qualityKey: 'maj7', ... }

// Parse a full progression
parseChanges('Dm7 G7 | Cmaj7');
// [{ root: 2, qualityKey: 'min7' }, { root: 7, qualityKey: 'dom7' }, ...]

Dynamic Chord Naming

const chord = buildChordInfo(0, 0); // I in C major = Cmaj7

// Full voicing
chordSymbol(chord, new Set([1, 3, 5, 7]));
// { symbol: 'Cmaj7', quality: 'Maj7' }

// Drop the 3rd → sus chord
chordSymbol(chord, new Set([1, 5, 7, 11]));
// { symbol: 'Csus4', quality: 'Sus4' }

// Add 9th without 7th → add chord
chordSymbol(chord, new Set([1, 3, 5, 9]));
// { symbol: 'Cadd9', quality: 'Add9' }

// Root and 5th only → power chord
chordSymbol(chord, new Set([1, 5]));
// { symbol: 'C5', quality: 'Power' }

Build Chord Info

// From a diatonic context (key + degree)
const ii = buildChordInfo(0, 1); // ii in C major
// { root: 'D', numeral: 'ii', type: 'm7', triad: ['D', 'F', 'A'], seventh: 'C', ... }

// From any root + quality (free mode)
const chord = buildFreeChordInfo(6, 'dom7'); // F#7
// { root: 'F#', name: 'F#7', triad: ['F#', 'A#', 'C#'], seventh: 'E', ... }

MIDI Voicing

import { getVoicingMidi, midiToNames } from '@toyrobot/chord-theory';

const chord = buildChordInfo(0, 0); // Cmaj7
const midi = getVoicingMidi(chord, new Set([1, 3, 5, 7]));
// [48, 52, 55, 59]

midiToNames(midi);
// ['C3', 'E3', 'G3', 'B3']

// Use with Web Audio, Tone.js, or any MIDI library
synth.triggerAttack(midiToNames(midi));

Chord Suggestions (Autocomplete)

getChordSuggestions('C');
// ['C', 'Cm', 'C7', 'Cm7', 'Cmaj7', 'Cdim', 'Caug', 'Csus4']

getChordSuggestions('Ebm');
// ['Ebm', 'Ebm7', 'Ebmaj7', 'Ebm7b5', ...]

API Reference

Core

| Function | Description | |----------|-------------| | parseChord(symbol) | Parse a chord symbol string → ParsedChord | | parseChanges(input) | Parse space/pipe-separated chord changes → ParsedChord[] | | getChordSuggestions(input, limit?) | Autocomplete chord symbols | | buildChordInfo(keyRoot, degIdx, useFlats?, system?) | Build chord info from diatonic context | | buildFreeChordInfo(rootPitch, qualityKey, useFlats?) | Build chord info from root + quality | | chordSymbol(chordInfo, activeIntervals) | Generate symbol for partial voicing | | noteName(pitchClass, useFlats?) | Pitch class → note name | | useFlatsForKey(keyPitch, system?) | Should this key use flat notation? | | buildScale(rootIdx, intervals, useFlats?, letterOffsets?) | Build a spelled scale |

Borrowed Chords

| Function | Description | |----------|-------------| | getBorrowedChords(keyRoot, currentSystem?, useFlats?) | All borrowable chords from parallel systems | | getParallelChord(keyRoot, degIdx, currentSystem?, useFlats?) | Chord from the next parallel system |

Reverse Lookup

| Function | Description | |----------|-------------| | findDiatonicMatches(rootPitch, qualityKey) | Find all diatonic contexts for a chord | | findMatchesForSymbol(symbol) | Same, but takes a chord symbol string |

Voicing

| Function | Description | |----------|-------------| | getVoicingMidi(chord, activeIntervals, baseOctave?) | Chord → MIDI note numbers | | midiToNames(midi) | MIDI numbers → note name strings |

Data

Raw data exports for advanced use: CHROMATIC, SCALE_SYSTEMS, CHORD_QUALITIES, QUALITY_ALIASES, ROOT_NAMES, HEPTATONIC_SYSTEMS, PARALLEL_SYSTEM.

Pitch Classes

All pitch parameters use integer pitch classes: 0 = C, 1 = C#/Db, 2 = D, ... 11 = B.

Scale Systems

Four heptatonic systems, each with 7 diatonic chords:

  • Major — I ii iii IV V vi vii°
  • Natural Minor — i ii° III iv v VI VII
  • Harmonic Minor — i ii° III+ iv V VI vii°
  • Melodic Minor — i ii III+ IV V vi° vii°

Plus augmented triad and diminished 7th symmetric systems.

Chord Qualities

31 chord types across triads, 7ths, and extended chords. 30+ notation aliases (e.g. Δ7 = maj7 = M7 = Maj7). See CHORD_QUALITIES and QUALITY_ALIASES for the full list.

Origin

Extracted from TOYROBOT, an interactive chord tone fretboard tool for guitarists and bassists.

License

MIT