Install
$ agentstack add skill-kennethreitz-pytheory-skill-scales-modes-and-tunings-with-pytheory ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Scales, Modes & Tunings
Scales and modes, the notes/intervals beneath them, and PyTheory's 16 tuning systems.
Scales & modes
from pytheory import TonedScale
ts = TonedScale(tonic="C4", system="western")
ts.scales # ('chromatic','major','minor','dorian','lydian', …)
s = ts["dorian"]
s.note_names # ['C', 'D', 'Eb', 'F', 'G', 'A', 'Bb', 'C']
[str(t) for t in s.tones] # ['C4', 'D4', 'Eb4', 'F4', …]
s.harmonize() # diatonic chords built on each degree
> Pentatonic & blues scales live in the blues system, not western: > TonedScale(tonic="E2", system="blues")["minor pentatonic"] (also > "major pentatonic", "blues", "major blues").
Which scale fits these notes?
Scale.recommend ranks scales by how well they contain a set of notes — great for "what can I solo with here?". Note the import: pytheory.Scale is an alias for TonedScale, so import the real class from pytheory.scales:
from pytheory.scales import Scale
Scale.recommend("C", "Eb", "G", "Bb", "D", top=3)
# [('C', 'aeolian', 1.0), ('G', 'aeolian', 1.0), ('C', 'dorian', 1.0)]
# -> (tonic, scale_name, fitness 0..1)
Detect the scale of a note set:
TonedScale(tonic="C4", system="western")["major"].detect("C","D","E","F","G","A","B")
# ('C', 'major', 7) -> (tonic, scale, matched-note count)
Tones, intervals, overtones
from pytheory import Tone
Tone.from_string("A4").frequency # 440.0
Tone.from_midi(69) #
Tone.from_frequency(440.0) #
Tone.from_string("C4").interval_to(Tone.from_string("G4")) # 'perfect 5th'
Tone.from_string("A2").overtones(4) # [110.0, 220.0, 330.0, 440.0]
[str(t) for t in Tone.from_string("C4").circle_of_fifths()] # ['C4','G4','D5','A5', …]
Twelve-tone rows (serialism)
A ToneRow is an ordering of all 12 pitch classes, each once. From it come the 48 forms (P/R/I/RI × 12 transpositions) and the row matrix. The transposition number is the pitch class the form begins on.
from pytheory import ToneRow
row = ToneRow.from_names("C","C#","E","D","F","D#","F#","A","G#","G","B","A#")
row.P(0); row.I(0); row.R(0); row.RI(0) # the four operations, starting on C
row.form("RI7") # any form by label
row.all_forms() # all 48, {label: [pitch classes]}
print(row.matrix_str()) # the 12x12 matrix (P→ R← I↓ RI↑)
row.is_all_interval # uses each interval 1–11 once?
Every row/column of the matrix is a permutation of 0–11 and the diagonal is all zeros — handy invariants if you ever need to sanity-check output.
Tuning systems & temperaments
from pytheory import SYSTEMS
list(SYSTEMS) # 16: 'western','indian','arabic','japanese','blues',
# 'gamelan','19-tet','31-tet','shruti', …
Build scales in any system, e.g. an Indian raga or Arabic maqam:
TonedScale(tonic="C4", system="indian").scales # the 10 thaats (parent scales)
TonedScale(tonic="C4", system="arabic")["..."] # maqamat
Ragas (Hindustani)
The indian system gives the ten thaats (parent scales). For the living ragas — ascending/descending lines, characteristic phrase, time of day, and rasa — use Raga, which intones them in the shruti (just) tuning, not 12-TET:
from pytheory import Raga
r = Raga.get("yaman")
r.aroha_swaras() # ['N.', 'R', 'G', 'M', 'D', 'N', "S'"]
r.avaroha_swaras()
r.note_names("D") # voice it in any key — Sa is movable
r.vadi, r.samvadi, r.time, r.rasa, r.jati
r.shruti_table("C") # each swara's just ratio + cents off 12-TET
r.just_ratios()["G"] # Fraction(5, 4) — the just major third
r.play("C4") # sitar, just intonation, light reverb (just=False = 12-TET)
Raga.names() # all 36
Raga.by_thaat("kafi")
Raga.by_time("night")
From the CLI: pytheory raga yaman --shruti --play (prints the shruti table, then plays it); pytheory raga --thaat bhairav lists ragas by thaat.
Temperament
Temperament affects the actual pitch (Hz) of a tone:
Tone.from_string("E4").pitch(temperament="just") # 330.0 (vs ~329.6 equal)
# Whole-score tuning: Score("4/4", bpm=90, system="shruti", temperament="just")
Tips
Scale.recommendandScale.detect-style helpers take note name strings.pytheory.Scaleis aliased toTonedScale; the staticrecommendlives on
pytheory.scales.Scale.
- Temperaments include
equal(default),just,meantone,pythagorean. - To actually play in an alternate system, pass
system=/temperament=to
Score(...) (see the composing skill).
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: kennethreitz
- Source: kennethreitz/pytheory-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.