Human-readable MIDI markup language compiler and tools
Project description
MIDI Markdown
Human-readable MIDI markup language for creating and automating MIDI sequences
✅ Production-Ready — 1090+ tests, 72.53% coverage | Real-time MIDI playback | 6 device libraries (300+ aliases)
🎹 Real-Time MIDI Playback (NEW)
Interactive Terminal UI with real-time MIDI playback, sub-5ms timing precision, and keyboard controls (Space/Q/R)
Table of Contents
- What is MIDI Markdown?
- Why MMD?
- Key Features
- Quick Example
- Getting Started
- Installation
- Usage
- Device Libraries
- Examples
- Documentation
- Contributing
- Roadmap
- License
What is MIDI Markdown?
The Problem: Musicians struggle with MIDI automation for live performances. A single preset change requires manually programming 3+ MIDI commands (Bank MSB, Bank LSB, Program Change). Traditional solutions—DAWs, raw MIDI files—are either not portable or completely unreadable.
The Solution: MIDI Markdown (MMD) provides human-readable, text-based MIDI automation designed specifically for live performance. Instead of cryptic hex values and binary files, you write semantic commands like cortex_load 1.2.0.5 that compile to precise MIDI sequences.
Why Choose MMD?
- Device aliases: Write
cortex_load 1.2.0.5instead of 3 cryptic MIDI commands (Bank MSB, LSB, PC) - Version control: Commit your automation to Git alongside your setlists—see exactly what changed between gigs
- Real-time playback: Interactive TUI with sub-5ms timing precision, keyboard controls (Space/Q/R), no DAW overhead
- 300+ pre-built aliases: 6 supported devices (Neural DSP Quad Cortex, Eventide H90, Line 6 Helix, HX Stomp, HX Effects, HX Stomp XL)
- Flexible timing: Absolute timecode
[mm:ss.ms], musical time[bars.beats.ticks], relative[+500ms], simultaneous[@] - Production-tested: 1090+ tests, 72.53% code coverage—built for reliability
Example: From Chaos to Clarity
# Without MMD: cryptic raw MIDI
- cc 1.32.2 # Bank MSB (what does this do?)
- cc 1.0.0 # Bank LSB (no idea!)
- pc 1.5 # Program Change (which preset?)
# With MMD: semantic, obvious
- cortex_load 1.2.0.5 # Load Setlist 2, Group A, Preset 5
Why MMD?
If you're currently managing MIDI automation for live performance, you might be wondering why MMD is better than other approaches. Here's how it compares:
| Aspect | Manual MIDI Programming | DAW Session Files | Raw MIDI Files | MIDI Markdown |
|---|---|---|---|---|
| Readability | Hex values, hard to scan | GUI-based, not portable | Binary, unreadable | Human-readable text ✓ |
| Version Control | Difficult to diff/merge | Large binary files | Binary diffs | Text-based, Git-friendly ✓ |
| Device Portability | Device-specific | Locked to DAW | Needs mapping tables | Device-agnostic core ✓ |
| Performance Tweaking | Manual editing tedious | Requires DAW open | Binary hex editing | Simple text editing ✓ |
| Reusability | Copy-paste error-prone | Project-locked | No structure | Aliases & imports ✓ |
| Real-time Editing | ❌ Not possible | Requires DAW running | ❌ Not possible | Interactive TUI ✓ |
Why musicians choose MMD:
- Version control: Commit your automation to Git alongside your setlists. See exactly what changed between gigs.
- Portable: Same automation works across any MIDI device. Use Quad Cortex one night, Helix the next—no rewiring needed.
- Device libraries: Pre-built aliases for 6+ devices (Quad Cortex, H90, Helix, HX effects). Create your own in minutes.
- Live-friendly: Edit and test automations on the fly with interactive playback. No DAW startup overhead.
- Human-readable: Comments, clear syntax, and intuitive timing make automation easy to understand and maintain.
Example: Switching from Neural DSP Quad Cortex to Eventide H90? Change one line (@import "devices/h90.mmd") and your automation adapts automatically.
Key Features
🎹 Real-Time MIDI Playback — Interactive TUI with play/pause/stop, sub-5ms timing precision, keyboard controls (Space/Q/R)
🎛️ Device-Specific Aliases — 300+ aliases for 6 devices (Quad Cortex, H90, Helix, HX Stomp, HX Effects, HX Stomp XL) — replace raw MIDI with semantic commands
📝 Human-Readable Syntax — Markdown-inspired format, version control friendly, designed for musicians not programmers
⚡ Multiple Timing Systems — Absolute [00:16.250], musical [8.2.240], relative [+500ms], simultaneous [@]
🔄 Advanced Automation — Variables, loops, conditionals, sweeps, generative patterns with random(), Bezier curves, LFO modulation, envelopes
📊 Comprehensive Output — MIDI files (formats 0/1/2), JSON export, CSV export (midicsv-compatible), Rich table display for debugging
Quick Example
Imagine you're setting up a live performance with your Neural DSP Quad Cortex and need to automate preset changes throughout your set. With traditional MIDI, you'd have to manually configure bank selects and program changes. With MML, you write human-readable code and let the compiler handle the complexity:
---
title: "Live Performance - Quad Cortex Automation"
tempo: 120
ppq: 480
---
# Import device-specific aliases for Quad Cortex
@import "devices/quad_cortex.mmd"
# Define reusable scene transitions with timing
@alias switch_scene {ch} {scene} {name}
- marker "{name}"
- cc {ch}.34.{scene} # CC#34 = scene select
- [+100ms] # Account for device latency
@end
# ============= INTRO (Clean Tones) =============
[00:00.000]
- tempo 120
- qc_load_preset 1 0 0 5 # Load preset 5 from Setlist 1
# Build tone with gain automation
[00:04.000]
- switch_scene 1 0 "Intro - Scene A (Clean)"
# ============= VERSE (Rhythm Tone) =============
[00:16.000]
- switch_scene 1 1 "Verse - Scene B (Light OD)"
# Boost volume for section
[00:20.000]
- cc 1.7.100 # Master volume to 100
# ============= CHORUS (Heavy Tone) =============
[00:32.000]
- switch_scene 1 2 "Chorus - Scene C (Heavy Distortion)"
# ============= SOLO (Lead Tone) =============
[00:48.000]
- qc_load_preset 1 0 0 12 # Switch to lead preset
- [+150ms]
- switch_scene 1 3 "Solo - Scene D (High Gain Lead)"
# ============= OUTRO =============
[01:04.000]
- switch_scene 1 0 "Outro - Back to Clean"
Compile it:
mmdc compile performance.mmd -o performance.mid
Play it live:
mmdc play performance.mmd --port "Quad Cortex MIDI"
What just happened:
- You imported Neural DSP's device library with 86+ pre-built aliases
- You wrote readable, structured code using
switch_sceneandqc_load_presetinstead of cryptic CC/PC numbers - Automatic delays are built in so your device has time to process messages
- The compiler generated precise MIDI timing (down to milliseconds)
- You can now sync your entire performance to your DAW or play it standalone in real-time
This is what makes MMD special: device automation becomes readable, reusable, and reliable.
Getting Started
New to MMD? Check out the Getting Started Guide for a 5-minute tutorial.
Installation
Recommended (pipx):
pipx install midi-markdown
mmdc --version
Alternative (pip):
pip install midi-markdown
Development (from source):
git clone https://github.com/cjgdev/midi-markdown.git
cd midi-markdown
uv sync # or: pip install -e ".[dev]"
Standalone executables (no Python required): Download from GitHub Releases for Linux, macOS, and Windows.
See Installation Guide for detailed platform-specific instructions.
Usage
CLI Commands
# Compile MMD to MIDI
mmdc compile song.mmd -o song.mid
# Real-time playback (NEW - Phase 3)
mmdc play song.mmd --port "IAC Driver Bus 1"
mmdc play song.mmd --port 0 --no-ui
mmdc play --list-ports
# Validate MMD syntax
mmdc validate song.mmd
# Quick syntax check
mmdc check song.mmd
# Show version
mmdc version
# Device library management
mmdc library list
mmdc library info quad_cortex
Python API
# TODO: API usage examples once implementation is complete
from midi_markdown import compile_mml
compile_mml("song.mmd", "output.mid", ppq=480)
Claude Code Skills
For Claude Code users: MIDI Markdown provides official Claude Code skills to enhance your development experience:
- mmd-writing - Help writing MMD files with correct syntax, timing, and commands
- mmdc-cli-usage - Help using the mmdc CLI effectively
Installation: Download the skills package from the latest release and run the included installation script. See the Claude Skills documentation for detailed instructions.
Benefits:
- ✅ Automatic syntax help when editing
.mmdfiles - ✅ CLI command suggestions and best practices
- ✅ Error troubleshooting and debugging assistance
- ✅ Example code and common patterns
Device Libraries
Device libraries enable semantic commands that replace raw MIDI sequences. Instead of manual CC/PC sequences, write cortex_load 1.2.0.5 for "Load Setlist 2, Group A, Preset 5"—much clearer and easier to maintain. MIDI Markdown includes 300+ pre-built aliases across 6 device libraries:
| Device | Aliases | Key Features |
|---|---|---|
| Neural DSP Quad Cortex | 86 | Preset loading, scene switching, I/O routing |
| Eventide H90 | 61 | Preset management, parameter control, MIDI mapping |
| Line 6 Helix Floor/LT/Rack | 49 | Snapshots, command center, routing |
| Line 6 HX Effects | 40+ | Preset switching, bypass, parameters |
| Line 6 HX Stomp | 39 | Compact control, scene switching |
| Line 6 HX Stomp XL | 40+ | Extended control, preset management |
Use device libraries to replace low-level MIDI with expressive, semantic commands:
# Instead of cryptic raw MIDI
- cc 1.32.2 # Bank MSB (unclear!)
- cc 1.0.0 # Bank LSB
- pc 1.5 # Program Change
# Write clear, semantic commands
- cortex_load 1.2.0.5 # Load Setlist 2, Group A, Preset 5 (obvious!)
# Import device libraries (Stage 8 coming soon)
# @import "devices/quad_cortex.mmd"
Examples
See the examples/README.md for a complete guide with learning path and feature matrix.
Quick Links:
- 00_hello_world.mmd - Simplest possible MMD file
- 05_multi_channel_basic.mmd - Multiple MIDI channels
- 09_comprehensive_song.mmd - All features combined
- 13_device_import.mmd - Device library imports
Documentation
Comprehensive documentation is available in the docs/ directory:
- Documentation Hub - Central documentation index with learning paths
- Getting Started - 5-minute tutorial for your first MMD file
- Installation Guide - Detailed setup for all platforms
- CLI Reference - Complete command-line interface documentation
- Alias System Guide - Learn to use aliases
- Device Library Creation Guide - Create your own libraries
- Alias API Reference - Complete API documentation
Contributing
Contributions are welcome! Whether you're a developer, musician, or device enthusiast, there are many ways to help improve MIDI Markdown.
Quick Start for Contributors
# Clone and setup
git clone https://github.com/cjgdev/midi-markdown.git
cd midi-markdown
# Install dependencies (UV is fast!)
uv sync
# Run tests
just test # or: pytest
Ways to Contribute
🎛️ Device Libraries (Great First Contribution!)
Creating device libraries is the easiest way to contribute—no complex coding required! If you have a MIDI device with documented CC/PC mappings:
- Create a new file in
devices/directory (e.g.,devices/axe_fx.mmd) - Add YAML frontmatter with device metadata
- Define aliases using the simple alias syntax (just MIDI CC/PC basics needed)
- Submit a PR—we'll help with any questions!
See Device Library Creation Guide for step-by-step instructions.
🐛 Bug Reports & Feature Requests
- Found a bug? Open an issue
- Have an idea? Request a feature
- Include MMD examples and expected vs actual behavior
💻 Code Contributions
Focus areas for development:
- Parser improvements (better error messages, recovery)
- New MIDI features (MPE, MIDI 2.0 support)
- CLI enhancements (interactive mode, better diagnostics)
- Documentation (tutorials, examples, guides)
Code Quality Tools
We use modern Python tooling for code quality:
# Run all quality checks
just check # or: ruff check . && mypy src
# Auto-fix issues
just fix # or: ruff format . && ruff check --fix .
# Run tests with coverage
just test-cov # or: pytest --cov
Development Workflow
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests and quality checks (
just check && just test) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
See CONTRIBUTING.md for detailed guidelines (coming soon).
Roadmap
Recently Completed
✅ Real-time MIDI playback with interactive TUI (Phase 3, Nov 2025)
- Sub-5ms event scheduler, tempo tracking, keyboard controls (Space/Q/R)
✅ Generative & modulation features (Phase 6)
- Random pattern generation, Bezier curves, LFO, envelope modulation
✅ Diagnostic output formats (Phase 1)
- JSON, CSV, Rich table display for analysis and debugging
✅ Core compilation pipeline (MVP Complete)
- Lark parser, alias resolution, variables, loops, sweeps, validation
- 1090+ tests, 72.53% code coverage
Planned Features
- REPL mode for interactive editing (Phase 2)
- MIDI Learn and device interrogation
- MIDI 2.0 support
- OSC integration
- Python/Lua scripting for advanced automation
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Inspired by Markdown's human-readable syntax
- Built for musicians and live performers
- Powered by modern Python tooling: UV, Ruff, Typer, pytest
Links
- Documentation Hub: docs/index.md
- Getting Started: docs/getting-started.md
- Specification: spec.md
- Examples: examples/README.md
- Issue Tracker: GitHub Issues
Built with ❤️ for musicians by musicians — If MMD helps your workflow, give us a ⭐ on GitHub!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file midi_markdown-0.1.0.tar.gz.
File metadata
- Download URL: midi_markdown-0.1.0.tar.gz
- Upload date:
- Size: 956.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5aafdc824a38f852a1a99beec66fb55b7b098b668162672c1b303d4900237a87
|
|
| MD5 |
d27d7a1861655218f3e9f64f41ea15a7
|
|
| BLAKE2b-256 |
463c025099f797c41b1704554b6abaac479a72c7d99212615b736db883d2e4d1
|
Provenance
The following attestation bundles were made for midi_markdown-0.1.0.tar.gz:
Publisher:
release.yml on cjgdev/midi-markdown
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
midi_markdown-0.1.0.tar.gz -
Subject digest:
5aafdc824a38f852a1a99beec66fb55b7b098b668162672c1b303d4900237a87 - Sigstore transparency entry: 702159933
- Sigstore integration time:
-
Permalink:
cjgdev/midi-markdown@3a67bbe0847bb65291babea4ceafebcbe159bec4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/cjgdev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3a67bbe0847bb65291babea4ceafebcbe159bec4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file midi_markdown-0.1.0-py3-none-any.whl.
File metadata
- Download URL: midi_markdown-0.1.0-py3-none-any.whl
- Upload date:
- Size: 193.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02e524d4e44927b5969510b9ce7029210f0e861bb7422712f79a183f4e1f554e
|
|
| MD5 |
f89a523e3f2a0a98794af7c584cb3f5d
|
|
| BLAKE2b-256 |
b242dcacd8f670f8a7b9ce6668adf6e02b5c4c212355e6843ee05aa792dc7272
|
Provenance
The following attestation bundles were made for midi_markdown-0.1.0-py3-none-any.whl:
Publisher:
release.yml on cjgdev/midi-markdown
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
midi_markdown-0.1.0-py3-none-any.whl -
Subject digest:
02e524d4e44927b5969510b9ce7029210f0e861bb7422712f79a183f4e1f554e - Sigstore transparency entry: 702159934
- Sigstore integration time:
-
Permalink:
cjgdev/midi-markdown@3a67bbe0847bb65291babea4ceafebcbe159bec4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/cjgdev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3a67bbe0847bb65291babea4ceafebcbe159bec4 -
Trigger Event:
push
-
Statement type: