whirlwind
whirlwind is a collaborative Reaper project sync tool for podcast co-editors. It helps a small team keep project files in sync through Cloudflare R2-backed storage.
Reaper Users
This project uses local paths for media. To make sure you are using local media paths in Reaper, see this recommendation from the docs:
In Options > Preferences > Project and check "Save project file references with relative pathnames". This ensures all media files are stored within the project folder.
Command Reference
)
)
Creating a New Episode Project
whirlwind new automates Reaper project setup for a new episode. It downloads your team's shared template from R2, wires in the recorded audio files, sets the project end marker, and pushes the result back to R2 — ready to open in Reaper.
Workflow
-
Copy the recorded WAV files into a new episode directory:
-
Run
whirlwind new <episode-directory-name>: -
Open the session in Reaper:
How it works
- Downloads
templates/default.rpp(or a named template) from R2 - Reads
[[new.tracks]]entries from~/.config/whirlwind/config.toml— maps filename glob patterns to named tracks in the template (e.g.*_erik_*.wav→erik) - Matched audio files are inserted into the corresponding template track, preserving its EQ and plugin chain
- Unmatched files (guests) are appended as plain tracks
- The outro track position is set to
project_end - 3s - The project end marker is set to
max(track_durations) - trim_seconds - The resulting
.rppis pushed to R2
Options
whirlwind new <episode-name> [OPTIONS]
Arguments:
<episode-name> Name of the episode directory under your working_dir
Options:
--template <name> Template to use (default: from config, else "default")
--trim-seconds <secs> Seconds to trim from project end (default: from config, else 0)
--assign <TRACK=FILE> Assign a file to a named track (repeatable)
--dry-run Show what would happen without writing or pushing anything
Use --assign to handle filenames that don't match your configured patterns:
Uploading your template
Before using whirlwind new, upload your Reaper template to R2:
The template should have empty <TRACK> blocks (no <ITEM>) for host mic tracks, and fully configured items for intro/outro tracks.
Config
Add an optional [new] section to ~/.config/whirlwind/config.toml to set defaults and configure track matching:
[]
= "default" # template name in R2 (without file extension)
= 2.0 # trim this many seconds from project end
[[]]
= "erik" # track name in the Reaper template
= "*_erik_*.wav" # glob pattern matched against the audio filename
[[]]
= "mike"
= "*_mike_*.wav"
[[new.tracks]] patterns are matched in order — the first match wins. Use --assign to override per-run when a filename doesn't match your usual patterns.
Purpose
- Keep Reaper project state aligned across collaborators.
- Provide a reliable sync workflow for podcast editing sessions.
- Reduce manual file handoffs between co-editors.
Common Workflows
This project uses just as the task runner for everyday development commands:
just test: run all testsjust test <filter>: run a filtered subset of testsjust fmt: auto-format codejust check: run formatting checks, clippy, and lintingjust build: create a release build
Stack
- Rust for the CLI and core sync logic
- Cloudflare R2 for remote object storage
- Reaper project files as the collaboration target