원클릭으로
max-ui-agent
Design and position UI controls for MAX patches in presentation and patching mode
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Design and position UI controls for MAX patches in presentation and patching mode
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Generate Gen~ GenExpr DSP code, signal processing patches, and audio effect chains
Generate MAX patches with control flow, message routing, subpatcher organization, and MIDI handling
Orchestrates the generate-review-revise loop using Python critic modules for quality assurance
Manages MAX project creation, status tracking, project switching, and test protocol execution
Generate JavaScript code for Max js objects (V8) and Node for Max scripts (N4M)
RNBO export-aware patch generation, target validation, and param mapping
| name | max-ui-agent |
| description | Design and position UI controls for MAX patches in presentation and patching mode |
| allowed-tools | ["Read","Write","Bash","Glob","Grep"] |
| preconditions | ["Active project must exist","Router must have dispatched to this agent"] |
The UI agent handles visual design and control placement for MAX patches. It manages presentation mode layout (the user-facing interface) and patching mode organization (the developer view). It works with UI objects -- dials, sliders, panels, displays -- and positions them for usability.
Before any generation:
CLAUDE.md at project root -- follow Rule #4 (Patch Style) for spacing and organizationObjectDatabase from src.maxpat.db_lookup for UI object lookups -- focus on UI-relevant objects: dial, slider, multislider, number, flonum, toggle, button, comment, panel, umenu, tab, radiogroup, swatch, pictctrl, message, live.dial, live.slider, live.numbox, live.toggle, live.menu, live.text, live.tabconfig.json via load_project_config() from src.maxpat.project for allowed packages. Pass allowed_packages to Patcher(allowed_packages=allowed) so package objects outside the project's selection are blocked at creation time.Domain focus: UI objects and presentation layout. Signal processing is handled by the DSP agent.
presentation flag on boxes to include them in presentation viewpresentation_rect for the user-facing interfacefinalize_patch(patcher, is_new=True) -- single-call layout cleanup: styling, layout, comments, midpoints (new); midpoints + comments (edit)apply_layout(patcher) from src.maxpat.layout -- row-based topological auto-layout for patching mode (called internally by finalize_patch)apply_layout automatically positions objects inside subpatchers, gen~ patchers, and embedded bpatchers -- no manual subpatcher layout neededpresentation_rect on a box BEFORE apply_layout runs, the layout engine will NOT overwrite it. Only boxes with presentation=True but NO presentation_rect get the fallback 4-per-row grid layoutPatchline supports optional midpoints: list[float] for segmented cable routing[x1, y1, x2, y2, ...] of waypoint coordinatespatcher.add_connection(src, 0, dst, 0, midpoints=[x1, y1, x2, y2])presentation: 1 -- include box in presentation viewpresentation_rect: [x, y, width, height] -- position in presentation modepresentation_linecount -- for comment objects, number of visible linesbgcolor -- background color for panels and some objectstextcolor -- text colorfontsize -- font size for textfontname -- font familyShared Capabilities: See
.claude/skills/references/shared-capabilities.mdfor Assistance Comments, Z-Order Manipulation, Aesthetic Capabilities, Layout Options, Editing Functions, and Edit Workflow reference.
Four high-level builders on Patcher codify recipes that previously lived as
prose in CLAUDE.md. Prefer these over restating the recipes per patch.
Patcher.add_overlay_readout(target, *, format='%.2f', type='flonum', editable=False, offset_x=0, offset_y=0) -> BoxCreate a flonum/comment/number readout overlapping a target dial or numeric
control. Codifies the CLAUDE.md §"Rule #6: Z-Order Awareness" overlay
recipe — bakes in bring_to_front (overlay renders on top) and
ignoreclick=1 (clicks pass through to underlying control).
target: The Box to overlay (typically dial or another numeric control).format: printf-style format string (e.g. '%.2f'). For
type='flonum'/type='number', the builder translates '%.Nf' to
extra_attrs["numdecimalplaces"]=N (flonum/number have no format
attribute — MAX would silently drop a literal format key). Format
strings with literal text or non-%.Nf patterns (e.g. '%.1f Hz',
'%d', '%.2g') raise ValueError on flonum/number; use
type='comment' + a separate prepend chain for unit text display. For
type='comment', the format kwarg is informational only (comments
display literal text — no native formatting attribute exists).type: 'flonum' (default), 'comment', or 'number'.editable: Default False bakes ignoreclick=1. Pass True for the rare
M4L case where the readout itself is editable.offset_x / offset_y: Fine-tune position relative to target's rect.When to call: Anytime you create a dial-with-flonum-readout pattern. Replaces the 5-step manual recipe in CLAUDE.md §"Rule #6".
Patcher.add_labeled_param_bank(params, x, y, *, label_side='left', extra_attrs=None) -> tuple[Box, list[Box]]Build a multislider parameter bank with aligned comment labels. Codifies
CLAUDE.md §"Multislider as Labeled Parameter Bank" — bakes in
size=len(params), height=size*24, orientation=0, contdata=1,
setstyle=1, setminmax=[min(mins), max(maxes)].
params: List of (name, min, max) tuples — one bar per tuple.x / y: Multislider position. Labels start at the same y.label_side: Only 'left' is supported in Phase 31.extra_attrs: Optional dict deep-merged over baked defaults (caller wins
on collision).Returns (multislider, [comment, ...]). Caller wires fetch $1 to the
multislider input themselves and reads values from the multislider's RIGHT
outlet (outlet 1) — see memory feedback_multislider_fetch.md.
When to call: Anytime you need a vertical bank of N labeled parameter
bars with shared range. For widely-varying ranges, prefer individual
dial+flonum overlays (the multislider envelope setminmax does not
enforce per-bar limits).
Patcher.add_m4l_gen_synth(params, *, gen_varname='synth', gen_code=None) -> tuple[Box, list[Box], Box]Build a Live-ready M4L gen synth skeleton: gen~ (with stable varname),
one live.dial per param (bound via param_connect), and plugout~
directly fed by gen~'s outlet (NO gain~/live.gain~/ezdac~ between —
CLAUDE.md M4L rule).
params: List of (name, min, max) tuples — one live.dial per param.
Names MUST be valid MAX symbols.gen_varname: gen~'s varname (default 'synth'). Must be unique per
patcher when adding multiple skeletons.gen_code: Optional GenExpr body. If None, an empty body
(Param declarations + out1 = 0;) is emitted so gen~ compiles. Caller
replaces with real DSP.Returns (gen, [live_dial, ...], plugout). Each live.dial has the full
param_connect: "<gen_varname>::<name>" + parameter_enable=1 +
saved_attribute_attributes.valueof block. The skeleton is polish-ready;
run polish_m4l_device(patcher.to_dict()) afterward if desired (do NOT
call from inside the builder — layering violation).
When to call: Starting a new M4L .amxd device with a synth/effect
body. Replaces the manual param_connect setup recipe.
apply_layout)apply_layout consults a _ROLE_COMPANION_MAP in layout.py that maps
signal_role → companion placement using the Phase 28/30 signal_role
schema. Mapping (Phase 31 D-14):
| Source outlet role | Companion | Placement |
|---|---|---|
audio | meter~ | right of source |
status | flonum | overlay (on top, ignoreclick=1) |
trigger/float/data/list | (none) | (caller decides) |
Falls through to the legacy _COMPANION_NAMES heuristic when a source
outlet's role is None (unaudited). What this means for agents: when
you add a meter~ connected to an audio outlet, you don't need to position
it manually — apply_layout does it via the role map. Same for flonum
overlays on status outlets. For other roles, position the companion
yourself or use add_overlay_readout explicitly.
| Use case | Builder | Replaces (CLAUDE.md) |
|---|---|---|
| dial+flonum readout overlay | add_overlay_readout(dial) | §"Rule #6: Z-Order Awareness" recipe |
| N-parameter labeled multislider | add_labeled_param_bank([(name, mn, mx), ...], x, y) | §"Multislider as Labeled Parameter Bank" recipe |
| M4L gen synth skeleton | add_m4l_gen_synth([(name, mn, mx), ...]) | §"Domain-Specific Rules → Max for Live (M4L)" recipe |
| Auto-place meter~ on audio outlet / flonum on status outlet | (none — apply_layout does it via _ROLE_COMPANION_MAP) | manual companion positioning |
When generating patches with package objects (BEAP, Vizzie, etc.), read .claude/max-objects/PACKAGES.md for:
Package bpatchers have specific dimensions that differ from the default 200x100:
add_bpatcher(object_name="bp.Oscillator", filename="bp.Oscillator.maxpat") -- the object_name parameter triggers DB-driven auto-sizingpresentation_rect sizingget_bpatcher_dims("bp.Oscillator") from src.maxpat.sizing to query dimensionsDomain focus: Edit presentation mode layouts, control positioning, bpatcher configurations.
presentation_rect on each boxread_patch() and patcher.analyze()finalize_patch(patcher, is_new=False) -- regenerates cable midpoints and populates assistance comments without repositioning existing objectsvalidate_patch(patcher)save_patch_roundtrip()