CLI to automate music render and upload, using Reaper and Python.
This app demonstrates how to programmatically control Reaper, from checking and temporarily changing global settings, un/muting tracks, to triggering renders of tracks. While built for personal music publishing and assuming certain Reaper project conventions, the app serves as an example of integrating with Reaper's Python API.
The following are the most common commands.
music renderSerially render the given list of Reaper projects, defaulting to the currently open project. Prints statistics comparing any previous render with the new output file.
The output looks like the following.
The command accepts many options, for example to render only 1 version of the song, or to upload asynchronously in addition to render.
music uploadSerially upload to a streaming service the renders of the given list of Reaper projects, defaulting to the currently open project.
music pathPrint the path to the current project.
music --help # list all commands
music command-name-here --help # list options for a specific command- A Python install with framework. For example,
with pyenv:
PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install <VERSION>
- SWS Extension
- uv
-
UV_PYTHON=path/to/framework/enabled/python uv pip install . -
Open Reaper
-
Configure Reaper for Python (per reapy's README)
path/to/framework/enabled/python -c "import reapy; reapy.configure_reaper()"- If successful, the command's output will be empty, except maybe a warning about being unable to reach REAPER's "distant" API.
-
Restart Reaper
Install for local development:
uv sync --all-extras
. ./venv/bin/activate # or however you add your virtualenv to your PATH
pre-commit installpytestBesides tests, checks are run on commit, after installing the pre-commit hook above, and on push. You can also run them manually.
pre-commit run --all-filesWhen using breakpoint(), to make the Python interactive debugger easier to
see, you'll probably want to disable rich
output, via the TERM environment variable. For example:
TERM=dumb music renderThis can happen if this project's Python version gets out of sync with Reaper's.
- Exit the command with Ctrl-C. You might see unexpected versions of Python in the stacktrace.
- Exit the modal dialog.
- In Reaper's reaper.ini, ensure the following values are your expected Python
version:
pythonlibdll64=libpython3.14.dylib pythonlibpath64=path/to/framework/enabled/python/lib/python3.14/config-3.14-darwin reascript=1
- In Reaper's reaper-extstate.ini and reaper-kb.ini, delete any lines mentioning "reapy".
- Restart Reaper.
- Re-run this project's install steps (again, with Reaper-compatible Python, and restarting Reaper at the end).
Coming soon: Conceptual overview of when and why to automate Reaper workflows.
- Reaper's Python API capabilities and limitations
- When automation makes sense vs. manual workflows
- Architecture decisions in this project
- Alternative approaches to Reaper automation
Reaper's Python API uses embedded Python that requires framework bindings to communicate between the DAW and Python scripts. Some Python installations lack this by default, like when installing Python via mise, pyenv, or uv. If Reaper is set to these incompatible Python versions, any commands sent from this project will exit with a stacktrace and may crash Reaper.
Running reapy's setup command from a compatible Python install will set the correct version in Reaper's preferences, without needing to use Reaper's GUI.
From then on, technically, this project can use a different Python version, even one without framework, as long as you don't re-run reapy's setup command, which will reset Reaper's Python version.