From strudel-agents
Practical music theory applied in Strudel — choosing keys and scales by mood (dorian, phrygian, lydian, mixolydian, pentatonics), diatonic chord progressions as scale degrees and chord symbols rendered with chord()/voicing() or n().scale(), basslines from rootNotes(), voice leading, tension and release, and melody-writing heuristics. Use when writing chord progressions, basslines, or melodies, choosing a key or mode for a mood, or harmonizing existing material in Strudel.
How this skill is triggered — by the user, by Claude, or both
Slash command
/strudel-agents:music-theoryThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Set the mode first; it does more for mood than any effect.
Set the mode first; it does more for mood than any effect.
| Scale | Mood | Strudel |
|---|---|---|
| minor (aeolian) | dark, serious | .scale("A:minor") |
| dorian | dark but cool, groovy (minor with a bright 6th) | .scale("D:dorian") |
| phrygian | tense, menacing (b2 against the root) | .scale("E:phrygian") |
| lydian | dreamy, floating (#4) | .scale("F:lydian") |
| mixolydian | warm, bluesy major (b7) | .scale("G:mixolydian") |
| major | bright, plain | .scale("C:major") |
| minor pentatonic | safe melodic minor palette — no wrong notes | .scale("A:minor:pentatonic") |
| major pentatonic | safe sunny palette | .scale("C:major:pentatonic") |
| harmonic minor | dramatic, exotic | .scale("A:harmonic:minor") |
n() values are zero-based scale degrees with .scale() (degree 0 =
root, 7 = root an octave up; negatives go below). The root may carry an
octave: "A2:minor".
n("0 2 4 7").scale("D:dorian")
n("0 .. 7").scale("E:phrygian").s("sawtooth")
chord() + voicing()voicing() turns symbols into concrete notes with smooth voice leading
between successive chords — this is your voice-leading engine; prefer it
over hand-stacked chords for progressions.
// minor i–VI–III–VII (epic/pop-dark), in A minor
chord("<Am F C G>").voicing().s("piano")
// jazz ii–V–I with 7ths, in C
chord("<Dm7 G7 C^7 C^7>").voicing().s("piano").room(.3)
// major I–V–vi–IV (the big-pop loop), in F
chord("<F C Dm Bb>").voicing().s("sawtooth").attack(.1).gain(.45)
// dorian two-chord vamp (i7–IV7), in D
chord("<Dm7 G7>").voicing().struct("x ~ x ~ ~ x ~ ~")
Stick to common symbol forms: m, 7, m7, ^7 (maj7), 9, m9,
sus4, b13. Steer the register with .anchor("e4").mode("below");
arpeggiate a voicing with .n("0 1 2 3") or .arp("0 2 1 3").
n().add(n(...)).scale()Move a chord shape diatonically by adding degrees — terse and always in key.
The add must be keyed (n(...)) and come before .scale(); a plain
.add("<...>") on a control pattern silently does nothing:
// triads on degrees 0, 5, 3, 4 of A minor (i–VI–iv–v)
n("[0,2,4]").add(n("<0 5 3 4>")).scale("A:minor").s("sawtooth").gain(.4)
rootNotes(octave) extracts each chord's root — the reliable way to keep
bass and harmony locked. Share one progression const between voices.
setcpm(96/4)
const prog = chord("<Am7 F^7 C^7 G7>");
$: prog.voicing().s("piano").gain(.6).room(.3)
$: prog.rootNotes(2).s("sawtooth").lpf(500)
.struct("x ~ ~ x ~ ~ x ~") // tresillo-ish bass rhythm
For non-symbol harmony, write the bass as alternating roots:
note("<a1 f1 c2 g1>*2").
G7 in C), the v or VII in minor, b2 in
phrygian, leaving melodies on non-chord tones, rising filter/register.<Am F G E7> resolves home harder than <Am F G C>.chord("<Am Am F E7>").voicing() // E7 makes the loop "lean" back to Am
~ is a note choice.// motif (cycle A) and varied answer (cycle B): same rhythm, new contour
n("<[0 1 2 ~ 4 ~ 2 0] [0 1 2 ~ 5 ~ 4 2]>")
.scale("D:dorian").s("triangle").gain(.55)
Pentatonic + off echo is a near-foolproof lead:
n("0 ~ 2 4 ~ 4 7 ~").scale("A:minor:pentatonic")
.off(1/8, x => x.add(note(7)).gain(.5))
Two shapes:
// A) alternate phrases per cycle: call, then answer
n("<[0 2 4 ~] [4 2 1 0]>").scale("G:mixolydian").s("piano")
// B) off() answers automatically, transposed and panned
n("0 ~ 3 ~ 2 ~ ~ ~").scale("E:minor:pentatonic")
.off(1/2, x => x.add(note(7)).pan(.8).gain(.6))
n() without .scale() selects samples, not pitches.note("0 2 4") is MIDI 0/2/4 — inaudibly low. Use n()+scale or note names..transpose(n), by scale steps with
.scaleTranspose(n); .add(n) on n() patterns moves by degrees.Deep reference: knowledge/tonal-and-theory.md.
npx claudepluginhub a5ta/strudel-agents --plugin strudel-agentsProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.