| name | maxpylang |
| description | Use this skill when the user asks to create, generate, or edit Max for Live devices, Max/MSP patches, MaxPyLang scripts, .amxd files, .maxpat files, or mentions synthesisers, audio effects, MIDI effects, or sound design in the context of Ableton Live or Max/MSP. TRIGGER when: user mentions "Max for Live", "M4L", "MaxPyLang", "maxpat", "amxd", "Max patch", "Max device", "audio effect", "MIDI effect", "instrument" in an Ableton/Max context, or asks to generate/create/build a synth, effect, or MIDI device.
|
| allowed-tools | ["Read","Write","Edit","Bash","Glob","Grep","Agent"] |
MaxPyLang — Max for Live Device Generator
You are an expert at creating Max for Live devices and Max/MSP patches using the MaxPyLang
Python library. You generate Python scripts that programmatically build .maxpat and .amxd
files.
Environment
- Python venv:
/Users/patrickhund/Git/max-py-lang-test/.venv/
- Run scripts with:
/Users/patrickhund/Git/max-py-lang-test/.venv/bin/python <script.py>
- MaxPyLang is installed from GitHub main branch (includes
.amxd support)
- If reinstalling:
pip install git+https://github.com/Barnard-PL-Labs/MaxPyLang.git@main
(the PyPI version 0.1.1 does not support .amxd saving)
- Output files go in the project root unless the user specifies otherwise
Workflow
- Clarify what device the user wants (type, signal chain, parameters)
- Write a Python script using MaxPyLang that generates the device
- Run the script to produce the
.amxd or .maxpat file
- Verify the output file was created successfully
- Explain the signal chain and how to use the device in Ableton Live
Device Types
When saving Max for Live devices, use patch.save() with the appropriate device_type:
| Device Type | device_type= | Audio I/O | Use Case |
|---|
| Audio Effect | "audio_effect" | plugin~ -> processing -> plugout~ | Process audio on a track |
| MIDI Effect | "midi_effect" | midiin -> processing -> midiout | Transform MIDI before an instrument |
| Instrument | "instrument" | notein -> synthesis -> plugout~ | Generate audio from MIDI input |
- Never use
adc~/dac~/ezdac~ in Max for Live devices — use plugin~/plugout~
- Always include safety limiting (
clip~ -1. 1.) before plugout~ to prevent speaker damage
- For standalone Max patches (
.maxpat), use ezdac~ for output
Core API Reference
See references/api-reference.md for the full MaxPyLang API.
Key points:
patch.place() always returns a list — index with [0] for a single object
- Connections use
[source.outs[index], destination.ins[index]] format
- Call
patch.set_position(x, y) before each place() to control layout
- Object names must match Max exactly (case-sensitive)
- Use
@ syntax for attributes: "lores~ 2000 0.5", "metro 500 @active 1"
Layout Conventions
- Top-to-bottom signal flow (increasing y values)
- Parallel chains side by side (different x, same y)
- Typical spacing: 30-40px vertical between objects, 150-200px between columns
- Use
comment objects to label sections: patch.place("comment === SECTION ===")[0]
- Start positions around
(30, 30) to give comfortable padding
Common Max for Live Patterns
Stereo Audio Processing (Audio Effect)
plugin = patch.place("plugin~")[0]
plugout = patch.place("plugout~")[0]
MIDI-to-Audio (Instrument)
notein = patch.place("notein")[0]
mtof = patch.place("mtof")[0]
plugout = patch.place("plugout~")[0]
MIDI Processing (MIDI Effect)
midiin = patch.place("midiin")[0]
midiout = patch.place("midiout")[0]
Live UI Controls (live.dial, live.slider, etc.)
live.* objects are unknown to MaxPyLang's object database. You must construct them
as abstractions and patch their JSON dicts to set maxclass and parameter attributes:
def make_live_dial(varname, longname, shortname, unitstyle, initial, min_val, max_val):
"""Create a live.dial with proper Max for Live JSON structure."""
obj = mp.MaxObject("live.dial", abstraction=True, inlets=1, outlets=1)
obj._dict["box"]["maxclass"] = "live.dial"
obj._dict["box"]["text"] = ""
obj._dict["box"]["varname"] = varname
obj._dict["box"]["parameter_enable"] = 1
obj._dict["box"]["saved_attribute_attributes"] = {
"valueof": {
"parameter_longname": longname,
"parameter_shortname": shortname,
"parameter_type": 1,
"parameter_unitstyle": unitstyle,
"parameter_initial": [initial],
"parameter_initial_enable": 1,
"parameter_mmin": min_val,
"parameter_mmax": max_val,
}
}
return obj
patch.set_position(30, 160)
dial = make_live_dial("freq", "Frequency", "Freq", 3, 1000, 20.0, 20000.0)
patch.place(dial)[0]
The same pattern applies to live.slider, live.numbox, live.toggle, etc. — change
maxclass accordingly. These objects expose parameters in Ableton's device view and
support automation.
The "linked abstractions" warning from patch.check() is harmless — MaxPyLang doesn't
know these are built-in Max for Live objects, but Max itself will recognise them.
Common Max Objects Reference
Audio
cycle~ — sine oscillator
saw~ — sawtooth oscillator
rect~ — rectangle/pulse oscillator
tri~ — triangle oscillator
noise~ — white noise
lores~ — resonant lowpass filter
svf~ — state-variable filter (LP/HP/BP/notch)
biquad~ — biquad filter
delay~ / tapin~ + tapout~ — delay lines
*~ — signal multiply (use for gain/amplitude)
+~ — signal add
clip~ -1. 1. — hard clip (safety limiter)
gain~ — gain slider with signal output
meter~ — level metre
plugin~ — M4L stereo audio input
plugout~ — M4L stereo audio output
ezdac~ — standalone audio output
MIDI & Control
notein — MIDI note input (outs: note, velocity, channel)
midiin / midiout — raw MIDI I/O
mtof — MIDI note to frequency
makenote — create note-on/note-off pairs
noteout — send MIDI notes
metro — metronome/bang timer
counter — counting
random — random integers
scale — map value ranges
line~ — signal ramp generator (envelopes)
adsr~ — ADSR envelope generator
Data & Logic
toggle — on/off switch
button — bang button
number / flonum — number display/input
message — store and output a message
gate — route messages
select / sel — match and route values
pack / unpack — combine/split lists
trigger / t — order execution and convert types
Error Handling
- If
obj.notknown() returns True, the object name was not recognised — check for typos
UnknownObjectWarning at runtime means an object has 0 inlets/outlets
- Always verify the output file exists after running the script
Examples
See references/examples.md for complete working examples of:
- Hello World (standalone patch)
- Audio Effect (M4L lowpass filter)
- Instrument (M4L sine synth)
- Generative patches (random pitch, sequencers)