brainstorming
Structured design dialogue that validates ideas before implementation begins.
mmd-device-library
Create custom MIDI device libraries for MIDI Markdown with aliases, parameters, and documentation. Use when the user wants to create device-specific aliases for hardware (guitar processors, synthesizers, effects units), document MIDI implementations, or build reusable command libraries.
Full skill instructions
This skill guides you through creating custom device libraries for MIDI Markdown. Device libraries provide high-level aliases for MIDI hardware, making automation code more readable and maintainable.
A device library is an MMD file containing:
Example usage:
@import "devices/my_device.mmd"
[00:00.000]
- my_device_preset 1.5 # Instead of: cc 1.32.0; pc 1.5
---
device: "My Device Name"
manufacturer: "Company Name"
version: 1.0.0
default_channel: 1
---
@alias device_preset pc.{ch}.{preset} "Load preset (0-127)"
Save as devices/my_device.mmd and import:
@import "devices/my_device.mmd"
[00:00.000]
- device_preset 1.42
You need:
Where to find:
Create devices/my_device.mmd:
---
device: "Device Name"
manufacturer: "Company"
version: 1.0.0
default_channel: 1
documentation: "https://example.com/midi-docs"
midi_channels: [1]
capabilities:
- program_change
- control_change
- sysex
---
# ==============================================
# Device Name MIDI Library
# ==============================================
# MIDI Implementation Overview:
# - Channel: 1 (default)
# - Program Change: 0-127
# - Control Change: See sections below
# - SysEx: F0 00 01 02 ... F7
# ==============================================
# Section 1: Preset Management
# ==============================================
@alias device_preset pc.{ch}.{preset:0-127} "Load preset (0-127)"
# Add more aliases...
Each alias needs a description:
@alias device_volume cc.{ch}.7.{value:0-127} "Set master volume (0-127)"
Description guidelines:
Create test file:
---
title: "Device Library Test"
ppq: 480
---
@import "devices/my_device.mmd"
[00:00.000]
- device_preset 1.0
- device_volume 1.100
Validate:
mmdc validate test.mmd
mmdc inspect test.mmd
Map device functions to CC or PC:
@alias device_function cc.{ch}.{cc_number}.{value} "Description"
Examples:
@alias amp_gain cc.{ch}.1.{value:0-127} "Amp gain (0-127)"
@alias delay_time cc.{ch}.12.{value:0-127} "Delay time (0-127)"
@alias reverb_mix cc.{ch}.91.{value:0-127} "Reverb mix (0-127)"
Combine multiple MIDI commands:
@alias device_load {ch}.{bank}.{preset} "Load bank and preset"
- cc {ch}.32.{bank} # Bank select LSB
- cc {ch}.0.0 # Bank select MSB
- pc {ch}.{preset} # Program change
@end
Provide default values for optional parameters:
@alias device_volume {ch}.{value=100} "Set volume (default: 100)"
- cc {ch}.7.{value}
@end
# Usage
- device_volume 1 # Uses default 100
- device_volume 1.75 # Uses 75
Named values for parameters:
@alias device_routing {ch}.{mode=series:0,parallel:1,a_only:2,b_only:3} "Set routing mode"
- cc {ch}.85.{mode}
@end
# Usage
- device_routing 1.parallel # Sends value 1
- device_routing 1.a_only # Sends value 2
Transform parameters before sending:
@alias device_tempo {ch} {bpm:40-300} "Set tempo (40-300 BPM)"
{midi_val = int((${bpm} - 40) * 127 / 260)}
- cc {ch}.14.{midi_val}
@end
# BPM 120 → MIDI value 39
# Preset loading
@alias cortex_load {ch}.{setlist}.{scene}.{preset} "Load complete preset"
- cc {ch}.32.{setlist} # Setlist
- cc {ch}.0.{scene} # Scene/group
- pc {ch}.{preset} # Preset
@end
# Scene switching
@alias cortex_scene pc.{ch}.{scene:0-7} "Switch scene (A-H = 0-7)"
# Expression pedals
@alias cortex_exp1 cc.{ch}.11.{value:0-127} "Expression pedal 1"
@alias cortex_exp2 cc.{ch}.12.{value:0-127} "Expression pedal 2"
# Stomp switches
@alias cortex_stomp_a cc.{ch}.81.{state:0-127} "Stomp A (0=off, 127=on)"
@alias cortex_stomp_a_on cc.{ch}.81.127 "Stomp A on"
@alias cortex_stomp_a_off cc.{ch}.81.0 "Stomp A off"
# Tap tempo
@alias cortex_tap_tempo cc.{ch}.80.127 "Tap tempo"
# Tuner
@alias cortex_tuner cc.{ch}.68.{state:0-127} "Tuner (0=off, 127=on)"
# Preset selection
@alias h90_preset pc.{ch}.{preset:0-127} "Load preset"
# Algorithm selection
@alias h90_algo_a cc.{ch}.82.{algo:0-52} "Algorithm for path A"
@alias h90_algo_b cc.{ch}.83.{algo:0-52} "Algorithm for path B"
# Mix control
@alias h90_mix cc.{ch}.84.{percent:0-100} "A/B mix (0=A, 100=B)"
# Routing
@alias h90_routing cc.{ch}.85.{mode=series:0,parallel:1} "Routing mode"
# Performance controls
@alias h90_bypass cc.{ch}.102.{state=active:127,bypassed:0} "Bypass"
@alias h90_infinity cc.{ch}.90.127 "Infinity (freeze)"
@alias h90_hotswitch cc.{ch}.91.127 "HotSwitch"
# Oscillator controls
@alias synth_osc1_wave cc.{ch}.70.{wave=saw:0,square:32,tri:64,sine:96} "OSC1 waveform"
@alias synth_osc1_detune cc.{ch}.71.{value:0-127} "OSC1 detune"
# Filter controls
@alias synth_filter_cutoff cc.{ch}.74.{value:0-127} "Filter cutoff"
@alias synth_filter_resonance cc.{ch}.71.{value:0-127} "Filter resonance"
# Envelope
@alias synth_env_attack cc.{ch}.73.{value:0-127} "Envelope attack"
@alias synth_env_decay cc.{ch}.75.{value:0-127} "Envelope decay"
@alias synth_env_sustain cc.{ch}.76.{value:0-127} "Envelope sustain"
@alias synth_env_release cc.{ch}.77.{value:0-127} "Envelope release"
# LFO
@alias synth_lfo_rate cc.{ch}.78.{value:0-127} "LFO rate"
@alias synth_lfo_depth cc.{ch}.79.{value:0-127} "LFO depth"
Organize aliases by function:
# ==============================================
# Preset Management
# ==============================================
@alias device_preset ...
@alias device_bank ...
# ==============================================
# Effects Controls
# ==============================================
@alias device_reverb ...
@alias device_delay ...
# ==============================================
# Expression Pedals
# ==============================================
@alias device_exp1 ...
@alias device_exp2 ...
Prefix with device name:
@alias cortex_preset ... # ✓ Clear
@alias preset ... # ✗ Too generic
Use descriptive names:
@alias amp_gain ... # ✓ Descriptive
@alias ag ... # ✗ Unclear
Group related functions:
@alias stomp_a_on ...
@alias stomp_a_off ...
@alias stomp_a_toggle ...
Use meaningful names:
{ch} # Channel
{preset} # Preset number
{value} # Generic value
{percent} # Percentage (0-100)
{state} # On/off state
{mode} # Mode selection
Include ranges in descriptions:
@alias device_tempo {ch} {bpm:40-300} "Set tempo (40-300 BPM)"
Different behavior based on parameters:
@alias smart_load {ch}.{preset}.{device_type} "Device-aware preset load"
@if {device_type} == "a"
- cc {ch}.32.0
- pc {ch}.{preset}
@elif {device_type} == "b"
- cc {ch}.71.{preset}
@end
@end
Include SysEx messages:
@alias device_patch_dump "Request patch dump"
- sysex F0 00 01 06 02 F7
@end
@alias scene_change_smooth {ch}.{old_scene}.{new_scene} "Smooth scene transition"
# Fade out old scene
- cc {ch}.7.curve(100, 0, ease-in)
# Switch scene
[+500ms]
- pc {ch}.{new_scene}
# Fade in new scene
[@]
- cc {ch}.7.curve(0, 100, ease-out)
@end
mmdc validate devices/my_device.mmd
Create comprehensive test file:
---
title: "Device Library Test Suite"
ppq: 480
---
@import "devices/my_device.mmd"
# Test all aliases
[00:00.000]
- device_preset 1.0
- device_volume 1.100
- device_function1 1.50
# ... test each alias
# Test edge cases
[00:10.000]
- device_preset 1.127 # Max value
- device_volume 1.0 # Min value
- device_function1 1.127 # Max value
# Inspect generated events
mmdc inspect test.mmd
# Compile and check MIDI
mmdc compile test.mmd -o test.mid
# Play back to verify
mmdc play test.mmd --port 0
Complete library template:
---
device: "Device Full Name"
manufacturer: "Company Name"
version: 1.0.0
default_channel: 1
documentation: "https://example.com/midi-implementation"
midi_channels: [1]
date_created: "2025-01-15"
date_modified: "2025-01-15"
author: "Your Name"
capabilities:
- program_change
- control_change
- sysex
notes: "Additional notes about this device"
---
# ==============================================
# Device Name MIDI Library
# ==============================================
/**
* MIDI Implementation Summary
*
* Channels: 1 (default), supports 1-16
* Program Change: 0-127 (presets)
* Control Change: See sections below
* SysEx: See SysEx section
*
* Quick Start:
* @import "devices/device_name.mmd"
* - device_preset 1.0
*
* Documentation: https://example.com/docs
*/
# ==============================================
# Preset Management
# ==============================================
@alias device_preset pc.{ch}.{preset:0-127} "Load preset (0-127)"
@alias device_bank_preset {ch}.{bank:0-7}.{preset:0-127} "Load bank and preset"
- cc {ch}.32.{bank}
- pc {ch}.{preset}
@end
# ==============================================
# Effects Controls
# ==============================================
@alias device_reverb cc.{ch}.91.{value:0-127} "Reverb mix (0-127)"
@alias device_delay cc.{ch}.92.{value:0-127} "Delay mix (0-127)"
# ... Add more sections as needed
Study existing device libraries:
# View Quad Cortex implementation
cat devices/quad_cortex.mmd
# View Eventide H90 implementation
cat devices/eventide_h90.mmd
# View Helix implementation
cat devices/helix.mmd
These provide patterns for:
# Validate
mmdc validate devices/my_device.mmd
# Test all aliases
mmdc validate test_suite.mmd
# Test with actual device
mmdc play test_suite.mmd --port "Device Name"
Add README or examples:
/**
* Usage Examples
*
* Basic preset load:
* - device_preset 1.42
*
* Bank select:
* - device_bank_preset 1.2.5
*
* Effects control:
* - device_reverb 1.75
*/
devices/ directory# Check import
grep "@import" your_file.mmd
# Verify alias definition
grep "@alias device_name" devices/my_device.mmd
# Test with raw MIDI
- cc 1.XX.YY # Instead of alias
# Check parameter count
@alias name {p1}.{p2} "..."
# Usage must match
- name 1.2 # ✓ Correct
- name 1 # ✗ Missing parameter
# Add range constraints
@alias func {ch}.{value:0-100} "..."
# Or use computed values
{clamped = min(127, max(0, ${value}))}
Skills:
Resources:
# Simple alias
@alias name command.{param} "Description"
# Multi-command alias
@alias name {p1}.{p2} "Description"
- command1
- command2
@end
# With defaults
@alias name {param=default} "Description"
# With enums
@alias name {param=opt1:val1,opt2:val2} "Description"
# With computed values
@alias name {param} "Description"
{computed = expression}
- command ${computed}
@end
1. mmdc validate devices/my_device.mmd
2. mmdc validate test_file.mmd
3. mmdc inspect test_file.mmd
4. mmdc play test_file.mmd --port 0
For complete device library examples, see the devices/ directory in the project.
Structured design dialogue that validates ideas before implementation begins.
Comprehensive design intelligence for web and mobile UI/UX across 10 technology stacks.
Comprehensive implementation plans for multi-step tasks, breaking down specs into bite-sized, testable steps.
Introduction to the obra skills system with mandatory skill invocation rules and best practices.
Execute a written implementation plan with critical review and task checkpoints.
Delegate independent tasks to specialized agents working concurrently with isolated context.
Isolated git worktrees with smart directory selection and safety verification.
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
Plan searchable and shareable content that drives traffic, builds authority, and generates leads.
README-first repository scanner that extracts commands and classifies reproduction candidates without executing them.
Brainstorm and prioritize marketing strategies tailored to your SaaS stage, budget, and goals.
Plan and optimize your website's page hierarchy, navigation, URL structure, and internal linking.
The world's fastest calendar for remote work
Capture, organize, and utilize your knowledge effortlessly.
Instant Summaries of Audio & Video Interviews with AnySummary
Transform PDFs into engaging mind maps.
Chat with any PDF instantly
Create an optimal daily plan using your voice
A productivity platform to centralize organizational knowledge and workflows with contextual AI assistance.
AskYourPDF Pricing Plans: Tailored to Your Needs