Status: revised 2026-05-07
RABBIT means "REAPER Accessibility Bootstrap & Bundle Installation Tool". Its job is to install and update REAPER, OSARA, SWS, ReaPack, ReaKontrol, FFmpeg (Windows only, opt-in), JAWS-for-REAPER scripts (Windows only, when JAWS is detected), apply small post-install configuration tweaks (e.g. adding the REAPER Accessibility ReaPack repository to ReaPack), and later additional packages, while keeping the workflow usable with screen readers on Windows and macOS.
The audience is REAPER users — including users who are not Rust developers, accessibility experts, or installer engineers. RABBIT must therefore choose sensible defaults, hide implementation detail, and avoid asking the user questions they cannot reasonably answer.
- One executable. RABBIT ships as a single self-contained binary per platform.
Run with no arguments → graphical wizard; run with any argument or
--help→ CLI. There is no separaterabbit-clibinary, no helper executable, no installer, no companion resource folder. - On Windows the executable does not pop up a console window when launched as a GUI; the same binary still attaches to the parent console when run from a command prompt with arguments.
- Release builds are optimized for file size first, then runtime speed
(
opt-level = "z", fat LTO, single codegen unit, stripped symbols, panic abort) so a download stays small for users on metered or slow connections. - The wizard is short, opinionated, and free of jargon. RABBIT picks the defaults a non-technical user would otherwise have to research, and presents results in plain terms ("REAPER 7.69 installed", "OSARA up to date") rather than internal mechanics ("detector: rabbit-receipt", "confidence: High", "PlannedAutomationKind::VendorInstaller").
- Install into an existing standard REAPER installation, into an existing portable REAPER installation, or set up REAPER plus the selected packages from scratch.
- Fully automate installation and update of REAPER, OSARA, SWS, ReaPack, ReaKontrol, the Windows-only JAWS-for-REAPER scripts, and (Windows-only, opt-in) FFmpeg's shared runtime libraries for REAPER's video decoder, without asking the user to run vendor installers or copy files manually in the normal flow.
- Apply small post-install configuration steps alongside the package
install — e.g. adding RABBIT's REAPER Accessibility ReaPack repository to
ReaPack's
reapack.ini. Steps surface in the same wizard tree under a separate "Configuration" group, run after the package install pipeline finishes, and are idempotent (re-running shows them as "already applied" and skips them). - Update REAPER and selected packages when newer versions are available.
- Detect installed versions where technically possible and clearly report "installed, version unknown" where it is not reliable.
- Prefer user-level installation paths for extensions so admin rights are not needed unless installing REAPER itself into a protected location.
- Preserve user configuration by default where possible. When OSARA is
selected, RABBIT replaces the active key map with the OSARA key map, after
backing up
reaper-kb.ini, only when that loses nothing of the user's: OSARA is new, orreaper-kb.inistill matches the installed OSARA key map (KeyMaps/OSARA.ReaperKeyMap, compared before the update overwrites it). Otherwise the key map stays and OSARA's "Merge OSARA key map" action brings the new bindings in. The Packages step shows an explicit checkbox so the user sees and can override the choice; the CLI does the same with--replace-osara-keymapand--preserve-osara-keymap. - Make every user-visible string localizable from the beginning. Embedded locales today: en-US, de-DE, fr-FR and it-IT.
- Build Windows and macOS artifacts automatically for every push in GitHub Actions so every commit can be tested from real binaries. Artifacts are the raw single-file binaries; no zipping.
- Publish signed release artifacts through a GitHub release pipeline so tagged versions become downloadable binaries with checksums and update metadata.
- Let RABBIT detect when a newer RABBIT version has been released and update itself with as little user interaction as practical while preserving accessibility and platform trust requirements.
- REAPER's own download page exposes the current version and platform-specific downloads. On 2026-04-23 it listed REAPER 7.69, released 2026-04-12. Source: https://www.reaper.fm/download.php
- REAPER's user guide says the resource path is shown from "Options > Show REAPER resource path in explorer/finder" and that Windows settings are not stored in the Windows Registry. Source: https://dlz.reaper.fm/userguide/ReaperUserGuide728c.pdf
- REAPER portable installs are based on a folder containing
reaper.ini. On Windows the installer has a "Portable install" option; on macOS the guide describes creating a folder withreaper.iniand copying the app there. Source: https://www.reaper.fm/userguide/ReaperUserGuide681c.pdf - OSARA installs into the REAPER user configuration/resource path, not the
REAPER program directory. Its Windows installer writes files into
UserPlugins,KeyMaps, andosara/locale; the standard Windows installer also writes an uninstall registryDisplayVersion. Source: https://raw.githubusercontent.com/jcsteh/osara/master/installer/osara.nsi - OSARA's macOS installer uses
~/Library/Application Support/REAPERfor a standard installation and asks for the folder containing portable REAPER for portable installs. Source: https://raw.githubusercontent.com/jcsteh/osara/master/installer/mac/Install%20OSARA.js - OSARA's update code embeds
OSARA_VERSIONinto the extension binary and compares it with the snapshot update JSON. Source: https://raw.githubusercontent.com/jcsteh/osara/master/src/updateCheck.cpp - SWS 2.14.0.7 is the latest stable version shown on the SWS site at the time of this design. The SWS changelog says SWS can be installed either by the traditional installer or via ReaPack 1.2.4.4 or newer. Sources: https://sws-extension.org/ and https://sws-extension.org/whatsnew.php
- SWS embeds Windows version resources using
SWS_VERSIONandSWS_VERSION_STR. Source: https://raw.githubusercontent.com/reaper-oss/sws/master/version.rc2.in - ReaPack's user guide says to install by placing the downloaded platform file
into REAPER's
UserPluginsdirectory and restarting REAPER. Source: https://reapack.com/user-guide - ReaPack 1.2.6 is the latest stable release shown by ReaPack at the time of this design. Source: https://reapack.com/
- ReaPack builds its version from
Extensions/ReaPack.ext, embeds Windows file version resources, and registers installed packages inReaPack/registry.db. Sources: https://raw.githubusercontent.com/cfillion/reapack/master/Extensions/ReaPack.ext, https://raw.githubusercontent.com/cfillion/reapack/master/src/buildinfo.rc, and https://raw.githubusercontent.com/cfillion/reapack/master/src/registry.cpp - ReaKontrol is a REAPER extension for Native Instruments Komplete Kontrol
keyboards. Its site says the current version is 2026.2.16.100, it requires
REAPER 6.37 or later, and there is no installer: on Windows and macOS the
user installs it by copying the downloaded file into REAPER's
UserPluginsfolder. The site also documentsreaKontrol/fxMapsunder the REAPER resource path for additional mapping files. Sources: https://reakontrol.jantrid.net/ and https://github.com/jcsteh/reaKontrol - wxWidgets can use native controls on Windows and has MSAA accessibility
support through
wxAccessible, but that documented custom accessibility class is Windows/MSAA-specific. Sources: https://wxwidgets.org/docs/faq/windows/ and https://wxd.sourceforge.net/wxWidgets-2.6/docs/html/wx/wx_wxaccessible.html - wxDragon is a Rust wxWidgets toolkit/wrapper. Its docs describe native
Windows, macOS, and Linux support, a Rust widget API, and XRC support through
include_xrc!. Source: https://docs.rs/wxdragon/latest/wxdragon/ - AccessKit is Rust accessibility infrastructure for custom-rendered UI toolkits and supports Windows/macOS adapters. Source: https://accesskit.dev/
- The REAPER Accessibility Hoard is a public file server that hosts the
JAWS-for-REAPER scripts under
https://hoard.reaperaccessibility.com/Custom%20actions,%20Scripts%20and%20jsfx/Windows%20Scripts/JAWS%20Scripts%20by%20Snowman/.
It is the rejetto/HFS server (
https://github.com/rejetto/hfs), which exposes a documented public REST API:POST /~/api/get_file_listreturns a JSON directory listing including each entry's name, size, and modified time, which RABBIT can use as the latest-version provider for the JAWS scripts. - REAPER's video decoder loads FFmpeg's shared runtime libraries
(
avformat-XX.dll,avcodec-XX.dll, ...) from<resource>/UserPlugins/. REAPER 7.66 added support for FFmpeg 8.x; RABBIT pins to the highest stable major REAPER's decoder is known to support and bumps that pin as new majors are added. Sources for shared Windows builds: Gyan.dev publishes a fixedffmpeg-release-full-shared.7zredirector that always points at the current stable, with a sibling*.verplain-text endpoint exposing the version. tordona/ffmpeg-win-arm64 publishes per-tag GitHub releases of ARM64 shared builds (ffmpeg-<ver>-full-shared-win-arm64.7z). Sources: https://www.gyan.dev/ffmpeg/builds/ and https://github.com/tordona/ffmpeg-win-arm64/releases. No equivalent scriptable source of shareddylibbuilds for macOS exists today — OSXExperts.net and evermeet.cx ship static binaries only, so the Mac side is deferred until a shared-build source materializes. - FFmpeg's vanilla Windows resource script (
fftools/fftoolsres.rc) attaches only a manifest, not aVERSIONINFOblock, so probing the PE resource offfmpeg.exereturns nothing useful. The reliable cross-vendor signal for the FFmpeg release version of an externally-installed copy is parsing the first line offfmpeg.exe -version's stdout (ffmpeg version <version> Copyright (c) ...). - ReaPack stores its enabled remotes in
<resource>/reapack.iniunder a[remotes]section. Each remote is a numbered key (remote<N>=<name>|<url>|<enabled>|<autoinstall>) withsize=declaring the count. ReaPack treatssizeas authoritative and assigns indices in addition order, so an idempotent "add this remote" upsert appends at the next index when the URL isn't already present. - Surge XT is a free hybrid synthesizer from the
Surge Synth Team. RABBIT tracks
the rolling nightly channel at
surge-synthesizer/surgereleases tagNightlyrather than the stablesurge-synthesizer/releases-xtrepo because the most recent stable (1.3.4, 2024-08-11) is the project's de facto abandoned channel — Surge XT now ships through nightlies. The nightly tag is static; the rolling build identity lives in the asset filenames (surge-xt-<platform>-NIGHTLY-<YYYY-MM-DD>-<short-sha>-…). The Windows installer is Inno Setup (surge-xt-win64-…-setup.exe, silent flags/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /TYPE=full /ALLUSERS); the nightly channel no longer ships a Win32 setup.exe and has no native ARM64 setup.exe, so Windows-on-arm hosts run the win64 installer under x64 emulation (ArchitecturesAllowed=x64compatible). The macOS DMG (surge-xt-macOS-…-dmg) wraps aproductbuilddistribution.pkgwhose sub-pkgs install the VST3, AU, CLAP, LV2, Standalone, and Effects formats under/Library/Audio/Plug-Ins/<format>/and the Resources sub-pkg under/Library/Application Support/Surge XT/. Both paths require admin rights, which is why RABBIT only offers Surge XT on standard REAPER targets — portable installations can't host the system-wide factory data anyway. - macOS elevation in
rabbit-platform::elevationraises the native AuthorizationServices dialog by wrapping the elevated command inosascript -e 'do shell script "…" with administrator privileges'. We picked that overSMJobBlessbecause the latter would require a separate signed helper bundle RABBIT doesn't ship, and over plainsudobecausesudocan't read a password from a GUI parent process. The osascript route is the same path Apple's own installer uses for GUI-driven elevation and is screen-reader friendly. The only consumer today is the Surge XTMountDiskImageAndRunPkgInstallerrunner.
Use Rust for the core application, package engine, and primary UI. The UI should prefer wxDragon so RABBIT can stay in one Rust codebase while still using mature wxWidgets-backed native controls.
Recommended implementation:
rabbit-corein Rust: detection, manifests, downloads, verification, install planning, backups, receipts, localization lookup, and logging.rabbit-platformin Rust: Windows/macOS native API isolation (file-version probes, registry probes, keychain/codesign, locale probe, plist parsing, disk-image mounting). One-way dependency fromrabbit-coretorabbit-platform.rabbitin Rust (single binary, formerlyrabbit-cli+rabbit-ui-wxdragon): the user-facing entry point. Built with the GUI feature on by default so a release binary can launch the wizard. Themainfunction dispatches by argv:- no arguments → run the wxDragon wizard
- any arguments or
--help→ run the CLI subcommand parser This single-binary model removes the duplicate distribution shape and makes it easy for users to memorize "the file isRABBIT.exe/RABBIT".
- Build release artifacts as self-contained executables wherever the platform allows. Embed required UI text, default localization resources, package metadata, and small static assets into the binary. Do not require a RABBIT installer for normal use.
Top-level main:
- Read
std::env::args_os(). - If exactly one argument is present (the program name itself), launch the
GUI. On Windows, the binary is built with
#![windows_subsystem = "windows"]so no console pops up; the GUI path usesAttachConsole(ATTACH_PARENT_PROCESS)only when the user explicitly asks for a banner/version on stdout. - Otherwise, hand the full argv to the CLI parser, which on Windows attaches to the parent console (or allocates one) so help output and command results are visible.
The CLI subcommand surface stays roughly what rabbit-cli exposes today;
moving it under the same crate is a packaging change, not a feature change.
Release builds are tuned for binary size:
[profile.release]
opt-level = "z" # optimize for size
lto = "fat"
codegen-units = 1
strip = "symbols"
panic = "abort"debug-assertions stays off in release. The CI release-mode artifact check
ensures the produced binary stays a single file with no neighboring DLL/dylib
dependency for the normal launch path.
This keeps the important logic and UI integration in Rust and avoids maintaining a separate C++/Objective-C/C ABI UI shell. The tradeoff is that wxDragon is a younger Rust layer over a mature toolkit, so RABBIT should keep the GUI thin and well tested. If wxDragon blocks required accessibility behavior, the fallback should be a direct wxWidgets shell with the same view-model boundary rather than rewriting the installer engine.
Full unattended installation is part of the product definition, not a stretch goal. For the first-class supported package set of REAPER, OSARA, SWS, ReaPack, and ReaKontrol, RABBIT should converge on one shared unattended execution path used by both the GUI and CLI.
Design rules:
- The normal supported path must not stop at "download and tell the user what to do next" for REAPER, OSARA, SWS, ReaPack, or ReaKontrol.
- For executable installers, RABBIT itself must download, verify, launch, wait for completion, evaluate exit status, and validate the installed result in the same run.
- The supported flow must not require the user to manually open an
.exe,.pkg,.app, disk image, or extracted archive and click through its setup UI on their own. - Any manual-attention flow for those packages is a temporary implementation gap, not acceptable steady-state product behavior.
- The GUI wizard and CLI must call the same package execution engine so unattended behavior is consistent and testable.
- RABBIT should prefer direct verified file installation for extensions when that is technically reliable, because it is more deterministic and accessible than driving third-party interactive installers.
- When RABBIT must use a vendor installer, it should do so with documented or validated silent arguments, explicit exit-code handling, integrity checks, and a post-install verification pass.
- "Run upstream installer" in the package model means RABBIT invokes the installer itself as part of the installation operation. It does not mean "download the installer and ask the user to run it manually later".
- If a package cannot currently be installed unattended on a platform, RABBIT should mark that as unsupported for that build/platform combination, not treat permanent manual installation as the finished design.
RABBIT should behave like a portable utility. A user should be able to download a single executable, run it from any writable folder, complete the REAPER setup or update, and remove the executable afterward. The executable may create cache, log, backup, report, and receipt files in explicit RABBIT locations under the selected REAPER resource path or user cache directory, but those files are operation data, not files required to start RABBIT.
Distribution goals:
- Windows: a single signed executable. No MSI, no setup program, no companion DLLs in the default launch path. The same executable serves both UI and CLI users via argv dispatch.
- macOS: a single signed and notarized executable. Use an
.appbundle layout only if macOS GUI launch policy forces it for a given wxWidgets/wxDragon shape; in that case the bundle stays self-contained with no separate RABBIT installer, and the CLI command-line surface still works against the binary inside the bundle. - Release artifact names follow
rabbit-<version>-<os>-<arch>[.exe](e.g.rabbit-0.2.0-windows-x86_64.exe,rabbit-0.2.0-macos-universal). macOS uses the literaluniversaltoken because the bare binary is a fat Mach-O with bothaarch64andx86_64slices — one artifact runs natively on both Apple Silicon and Intel hosts. This makes successive downloads distinguishable on disk, calls out the build's architecture explicitly, and works around the macOS-binary-without-extension ambiguity. Users may rename the file after downloading; the self-update apply step swaps in place under whatever filename the running binary has, not under the downloaded file's name. - CI artifacts and GitHub release assets are the raw single-file binaries plus
per-file SHA-256 sums. No
.zipwrapper is required for single-file artifacts; release notes link directly to the per-platform binaries. - Do not require separate locale files, XRC files, icons, package manifests, or certificates beside the executable for the default experience.
- Store downloads in the normal RABBIT cache directory and allow the cache to be deleted safely.
- Store install receipts, backups, and reports in the selected REAPER resource path so they travel with portable REAPER installations when possible.
- Do not write RABBIT program settings to the Windows Registry. If user preferences become necessary, keep them optional and user-scoped.
Implementation rules:
- Use
include_str!,include_bytes!, or generated Rust data for required built-in resources. - Treat external locale/resource directories as optional developer or advanced override paths, not runtime requirements.
- Keep wxDragon/wxWidgets deployment self-contained for release builds. The release check must verify that launching RABBIT does not depend on DLLs or dylibs sitting beside the executable unless the platform's GUI framework requires a signed app bundle layout.
- Any temporary extraction of embedded helpers must go to a temporary directory, be integrity-checked, and be cleaned up best-effort.
- The same portability rule applies to self-update: updated binaries should replace the old RABBIT binary or app bundle in place, not install a separate long-lived updater application.
RABBIT should have first-class delivery automation from the beginning. The design target is that every push produces testable platform artifacts and every tagged release produces end-user release assets plus update metadata.
GitHub Actions build pipeline for every push:
- Trigger on every push and pull request.
- Build RABBIT on at least:
windows-latestfor the Windows executablemacos-latestfor the macOS app or executable artifact
- Run the normal Rust checks on both platforms:
- formatting
- unit/integration tests
- release-mode build
- Build the distributable artifact shape, not only debug binaries:
- Windows: a single
RABBIT.exe - macOS: a single
RABBITexecutable (or a self-contained signed.appbundle if macOS GUI launch policy requires it for the chosen wxWidgets/wxDragon shape)
- Windows: a single
- Upload build artifacts to the workflow run so every push has downloadable
test binaries. Single-file artifacts upload as the bare file; no
.zipwrapper is added on top of an already-single-file binary. - Publish per-file SHA-256 sums alongside the artifacts so testers can verify what they ran.
Live-upstream smoke pipeline:
- A separate scheduled workflow runs each day against the real upstream
download URLs so vendor-side changes (relocated assets, new archive
layouts, expired redirectors) trip CI before they trip a user. The
current workflow is
macos-smoke.yml, which exercises the OSARA / SWS / ReaKontrol / REAPER macOS install paths onmacos-latest. The Windows-side smoke (FFmpeg via Gyan + tordona, plus the existing Windows install paths) is on the open-questions list — adding it requires a parallelwindows-smoke.ymlandwindows_upstream_smoke.rstest file.
GitHub release pipeline:
- Trigger on a version tag such as
vX.Y.Z, or on an explicit release workflow dispatch that creates the tag as part of the release process. - Rebuild Windows and macOS release artifacts from the tagged commit in a clean GitHub Actions environment.
- Produce release attachments:
- Windows artifact
- macOS artifact
- SHA-256 checksums
- machine-readable release/update manifest
- Apply code signing where available:
- Windows Authenticode signing for
RABBIT.exe - macOS code signing and notarization for the app bundle or executable
- Windows Authenticode signing for
- Generate release notes from a changelog or tag diff, with manual override for accessibility-relevant release notes.
- Publish the GitHub Release only after artifacts, checksums, signing, and update metadata are complete.
Release metadata:
- Each published release should expose enough machine-readable metadata for
RABBIT self-update, including:
- semantic version
- release channel (
stable, later optionallybeta) - publish timestamp
- per-platform download URL
- expected SHA-256
- minimum supported previous RABBIT version if a breaking updater transition is ever needed
- The release workflow should emit a stable JSON manifest asset or equivalent update feed derived from the GitHub Release so the updater does not need to scrape human-written release notes.
Suggested workflow layout:
.github/
workflows/
ci.yml
release.yml
RABBIT should be able to update itself from GitHub Releases with minimal user interaction while staying accessible and verifiable.
Updater design goals:
- Check for RABBIT updates separately from package updates for REAPER and its extensions.
- Use the GitHub release/update manifest as the authoritative source for the latest RABBIT version and platform artifact URL.
- Compare versions using strict semantic versioning for RABBIT itself.
- Default behavior should be:
- detect newer RABBIT release
- present a short accessible prompt
- download in the background after confirmation
- apply the update with one restart/replace step
- Advanced later option:
- support a user preference for automatically downloading stable RABBIT updates and applying them on the next restart
Updater flow:
- On startup, or on explicit
Check for RABBIT updates, fetch the signed or checksum-validated release manifest from the configured GitHub release channel. - If the current RABBIT version is already current, report that plainly.
- If a newer version exists, show:
- current version
- available version
- release channel
- short release notes or a link to them
- After confirmation, download the platform artifact to a temporary update staging directory.
- Verify:
- HTTPS transport
- expected SHA-256 from release metadata
- Windows signature or macOS code signing/notarization where applicable
- Stage the replacement.
- Replace RABBIT with the new version using the smallest platform-appropriate restart flow.
- Relaunch the updated RABBIT instance and confirm the new version.
Platform update strategy:
- Windows single-executable build:
- RABBIT cannot replace its own running
.exein place. - Stage the new executable beside the current one or in a temporary directory.
- Launch a very small temporary updater helper process or script whose only job is to wait for RABBIT to exit, swap the executable, and relaunch RABBIT.
- The helper must be ephemeral, integrity-checked, and cleaned up best-effort.
- RABBIT cannot replace its own running
- macOS app bundle build:
- Stage the new signed/notarized app bundle in a temporary directory.
- After RABBIT exits, replace the existing bundle atomically where possible and relaunch it.
- Preserve the app bundle path so Dock aliases and user expectations do not break.
Updater safety rules:
- Never apply a RABBIT self-update while a package installation/update operation is running.
- Never replace RABBIT with an unsigned or checksum-mismatched artifact.
- Keep one rollback copy of the previously running RABBIT binary or bundle until the first successful restart of the updated version.
- Log the update attempt and result in a plain text and machine-readable report.
- If self-update fails, RABBIT must continue running the existing version and report the error without leaving itself half-replaced.
CLI and UI expectations:
- CLI should expose explicit commands later such as:
rabbit self-update checkrabbit self-update apply
- GUI should expose:
- automatic startup check
- manual
Check for RABBIT updates - accessible progress/status during download and replacement
- Use native controls only: buttons, check boxes, radio buttons, list views, tree views, text fields, progress controls, and standard dialogs.
- Avoid custom drawing, canvas controls, owner-drawn lists, and grid controls in the main workflow.
- Every control needs an accessible name, role, state, keyboard focus, and visible label.
- Every screen must work by keyboard only, with a predictable tab order and mnemonic accelerators.
- Progress must be exposed as both a progress bar and a text status line.
- Errors must be plain text, selectable/copyable, and available in a final report.
- The test matrix for every release must include NVDA and Narrator on Windows, plus VoiceOver on macOS. JAWS should be included before public beta.
The UI is a short, jargon-free wizard. Defaults are chosen so a non-technical user can finish the install by pressing Next a few times.
-
Target
- One concise control: pick a detected REAPER, or pick "Install or update a portable REAPER folder" and choose the folder.
- Detected installations show simply as "REAPER 7.69 in
<path>" — no architecture, no detection-confidence label, no evidence list. Those remain available in the saved report and from the CLI for advanced users.
-
Version check
- A dedicated progress page with a progress bar, one status line ("Checking OSARA…") and a hidden error region that only appears if a fetch failed.
- On success the wizard auto-advances to the package list. On failure the page surfaces the error lines and lets the user go back or quit.
-
Packages
- Tree view with two top-level groups: Packages and
Configuration. Packages contains REAPER, OSARA, SWS, ReaPack,
ReaKontrol, FFmpeg (Windows only), JAWS scripts (Windows only), and
later additions; each row reads as plain text "OSARA — installed
2024.3.6, latest 2026.2.16, will update". Configuration contains
opt-in post-install tweaks (currently: "Add the REAPER Accessibility
ReaPack repository to ReaPack"); rows that are already applied or
whose dependency package isn't in the install plan are disabled with
a short status tag in the row label
(
(already applied),(requires ReaPack)). - Parent group nodes show a half-checked / tristate state when only
some of their children are ticked. Toggling the parent propagates to
every actionable leaf below it; clicks and Space keystrokes on
not-actionable leaves are pre-empted before native processing so
screen readers don't announce a phantom "checked" state that would
immediately revert. The checkboxes are real native controls
(
TVS_CHECKBOXESon Windows with a custom three-image state list for the tristate parent,wxDataViewtoggle renderer with a customCustomDataViewTreeModelon macOS/Linux) so screen readers announce them as proper checkboxes, not as "graphic" or "static text". - The selected row's details pane shows the package's localized
description (one or two plain-language sentences explaining what the
package is and why a user might want it). The same description is
exposed by the CLI via
rabbit packages, so users can read about every package before deciding to install it. - Defaults: install or update missing/outdated recommended accessibility packages, plus apply every recommended Configuration step whose dependency is satisfied and which isn't already applied.
- OSARA key map: an explicit checkbox stays on the Packages page so the
user sees and controls what RABBIT will do with
reaper-kb.ini. Default is replace-with-backup for a new OSARA and for a key map that is still the installed OSARA key map (scripts, order and binding comments aside), and keep for any other key map. The short note next to the checkbox says which case applies in the active locale. The CLI makes the same choice unless--replace-osara-keymapor--preserve-osara-keymapis passed.
- Tree view with two top-level groups: Packages and
Configuration. Packages contains REAPER, OSARA, SWS, ReaPack,
ReaKontrol, FFmpeg (Windows only), JAWS scripts (Windows only), and
later additions; each row reads as plain text "OSARA — installed
2024.3.6, latest 2026.2.16, will update". Configuration contains
opt-in post-install tweaks (currently: "Add the REAPER Accessibility
ReaPack repository to ReaPack"); rows that are already applied or
whose dependency package isn't in the install plan are disabled with
a short status tag in the row label
(
-
ReaPack donation acknowledgement (only when ReaPack is being installed or updated this run)
- Dedicated wizard page that mirrors the donation hint from https://reapack.com/. Plain language, in the active locale: ReaPack is free software, donations are optional, here is the donation URL.
- A focusable link to https://reapack.com/donate and an explicit checkbox or "I understand, continue" control. Continue is disabled until the acknowledgement is set. Going back to step 3 clears the acknowledgement so the user always re-confirms after changing the selection.
- In the CLI, the same acknowledgement is surfaced as an interactive
prompt before staging. For unattended use the user passes
--accept-reapack-donation-notice; without it,apply-packages/setuprefuses to stage ReaPack and exits non-zero with a clear message that points at the flag. - Skipped automatically on runs where ReaPack is neither installed nor updated.
-
Review
- Short plain-language summary: target path, packages to be installed or updated, an indication that backups will be made if any existing files will be replaced. No backup-file paths, no admin-prompt enumeration, no planned-execution metadata in the GUI summary; all of that is still written to the saved report and exposed by the CLI.
-
Install/update progress
- Single progress bar plus one current-step line. A "Show details" toggle reveals the underlying log for users who want it; collapsed by default.
-
Done
- One sentence summarizing success or failure.
- Buttons: Launch REAPER, Open resource folder, Save report. The signature-verification counts, lock-file paths, and similar diagnostics stay in the saved report.
Streamlining rules (apply when adding new wizard text):
- Default to one sentence per element. If a control needs more, the second sentence belongs in the saved report, not the wizard.
- Never expose internal identifiers (detector names, automation kinds, plan action enums, lock-file paths, SHA-256 prefixes) to the GUI user.
- Power-user output (full plan, full execution log, verdicts) stays reachable through the CLI and the saved report.
Represent every candidate as:
Installation {
kind: Standard | Portable,
app_path: PathBuf,
resource_path: PathBuf,
version: Option<Version>,
architecture: Option<Architecture>,
writable: bool,
confidence: High | Medium | Low,
evidence: Vec<Evidence>
}
Windows standard detection:
- Resource path:
%APPDATA%\REAPER. - App candidates:
%ProgramFiles%\REAPER\reaper.exe%ProgramFiles(x86)%\REAPER\reaper.exe- uninstall registry entries, treated only as hints.
- Version: Windows file version metadata where available; otherwise optional runtime probe.
Windows portable detection:
- User-selected folder is authoritative.
- Auto-detected portable candidates must contain
reaper.exeandreaper.ini. - Resource path is the portable folder.
macOS standard detection:
- App candidates:
/Applications/REAPER.app/Applications/REAPER64.app/Applications/REAPER-ARM.app
- Resource path:
~/Library/Application Support/REAPER. - Version: app bundle
Info.plistwhere available; otherwise optional runtime probe.
macOS portable detection:
- User-selected folder is authoritative.
- Candidate folder should contain a REAPER app bundle and normally
reaper.ini. - Resource path is the selected folder.
REAPER runtime probe:
- Optional later enhancement: launch REAPER in a controlled way with a temporary
ReaScript that calls
reaper.GetAppVersion(). This is more accurate than binary metadata but must never be used silently if it would disturb the user or open a visible DAW session unexpectedly.
There is no single generic, external "REAPER extension version" API that RABBIT should rely on. Detection must be package-specific and confidence-scored.
| Component | Primary detector | Fallback detector | Confidence notes |
|---|---|---|---|
| REAPER | executable/app metadata or optional GetAppVersion() runtime probe |
presence of app only | Runtime probe is most accurate, metadata is good enough for normal installs. |
| OSARA | RABBIT receipt after RABBIT-managed install; Windows standard uninstall DisplayVersion |
binary string scan for embedded OSARA_VERSION; presence of reaper_osara* |
Portable/mac installs do not have a universal external version registry. Binary scan is useful but should be marked best-effort. |
| SWS | RABBIT receipt; Windows PE ProductVersion; ReaPack registry if installed by ReaPack |
binary metadata/string scan; presence of reaper_sws* |
Prefer ReaPack registry for ReaPack-managed SWS. |
| ReaPack | RABBIT receipt; Windows PE ProductVersion; ReaPack self-entry in ReaPack/registry.db after first launch |
presence of reaper_reapack* |
The registry DB may not exist until ReaPack has run inside REAPER. |
| ReaKontrol | RABBIT receipt after RABBIT-managed install | best-effort binary metadata if available; presence of reaper_kontrol* |
No installer or registry-based detector is expected; validate binary metadata quality during implementation. |
| FFmpeg | RABBIT receipt after RABBIT-managed install; ffmpeg.exe -version parsed from stdout's first line |
StringFileInfo ProductVersion of an FFmpeg executable (only present when a vendor patches it in); libavformat-major filename heuristic (avformat-62.dll → FFmpeg 8.0.0, mapped via lib_major - 54) |
Vanilla FFmpeg attaches only a manifest to its binaries; VS_FIXEDFILEINFO of ffmpeg.exe carries libavutil's version, not the FFmpeg release. Spawning ffmpeg.exe -version is the only reliable vendor-independent way to recover the patch level for an externally-installed copy; the libavformat-major fallback recovers only the major when no executable is present. |
| Surge XT | RABBIT receipt after RABBIT-managed install (records the NIGHTLY-YYYY-MM-DD-sha token verbatim) |
read_file_version_parts on the system VST3 bundle — Windows PE VERSIONINFO of Contents\x86_64-win\Surge XT.vst3 inside <CommonProgramFiles>\VST3\Surge Synth Team\Surge XT.vst3\; macOS CFBundleShortVersionString of /Library/Audio/Plug-Ins/VST3/Surge XT.vst3/Contents/Info.plist |
The vendor-installed binary still carries the most recent stable semver (e.g. 1.3.4) — Surge XT doesn't stamp nightlies with their date+sha. Receipt-driven detection produces the exact nightly token; the file-metadata fallback reports the stable semver, which compares lower than any NIGHTLY-… under Version::cmp_lenient so the planner naturally schedules an Update. |
| ReaPack packages | ReaPack/registry.db table entries.version |
none | This is the best source for packages ReaPack knows about. |
RABBIT should keep its own receipt in each REAPER resource path:
<resource_path>/RABBIT/install-state.json
The receipt should record package id, installed version, source URL, SHA-256, installed files, backup files, install time, RABBIT version, and target architecture. This is authoritative only for files RABBIT installed. If the user later changes files manually, RABBIT should show that the receipt and disk state do not match.
Use a manifest-driven package system so future packages can be added without rewriting the installer engine.
TODO (docs): properly document the manifest schema. The manifest (
crates/rabbit-core/embedded/packages/builtin-packages.json) has grown a data-drivengithub_releaseblock (spike branchspike/data-driven-github-provider) that lets a GitHub-release plugin be added/maintained with a manifest entry alone — no Rust. Once that direction is adopted, write a proper schema reference covering: everyPackageSpec/EmbeddedPackageSpecfield; thegithub_releaseblock (repo,release="latest"|{ "tag": … },version_from=tag_name|asset_name, theassetsselectors witharch/name_prefix+name_suffix/exact_name,artifact_kind,install_destination); which packages stay "snowflakes" (bespoke provider enums) and why; and a worked "add a new package" example. Keep it close to the manifest (e.g. abuiltin-packages.mdnext to the JSON) so contributors find it.
PackageSpec {
id,
display_name_key,
display_description_key,
package_kind,
required,
recommended,
requires_user_acknowledgement,
min_reaper_version,
supported_platforms,
supported_architectures,
latest_version_provider,
artifact_provider,
detectors,
install_steps,
uninstall_steps,
backup_policy
}
Every package ships a display_description_key that resolves to a one- or
two-sentence localized description of what the package is and why a user
might want it. The wizard surfaces the description in the package details
pane (the same spot that today shows the handling/version block); the CLI
exposes it via rabbit packages so non-technical users can read about
REAPER, OSARA, SWS, ReaPack, ReaKontrol, and the JAWS scripts before
deciding what to install.
requires_user_acknowledgement is set on packages whose upstream policy or
licensing posture asks for an explicit acknowledgement before install — see
the ReaPack donation rule below. Default is false. When set, RABBIT must
not start the install for that package until the user has confirmed the
package-specific acknowledgement message in the GUI (a dedicated wizard
page) or in the CLI (an interactive prompt or an explicit
--accept-<package>-notice flag for unattended runs).
Initial package kinds:
reaper_app: vendor installer, dmg/app copy, or portable creation.user_plugin_binary: copy one or more extension binaries intoUserPlugins. Some packages ship a single extension DLL (OSARA, SWS, ReaPack, ReaKontrol); others ship a runtime bundle whose entirebin/folder lands inUserPlugins(FFmpeg). The install pipeline supports both shapes via the artifact kindsExtensionBinary(raw single-DLL download),Archive(zip carrying a single matching binary),DiskImage(macOS DMG), andSevenZipArchive(the FFmpeg.7zwhose everybin/<file>is flattened intoUserPlugins). A single receipt covers all extracted files for the multi-file case.keymap: copy intoKeyMaps, optionally replacereaper-kb.iniwith backup.reapack_package: install/update through ReaPack later, once ReaPack is present and REAPER has been launched.screen_reader_scripts: copy a screen-reader-specific script bundle into the user's screen-reader profile (e.g. JAWS scripts under%APPDATA%\Freedom Scientific\JAWS\<version>\Settings\enu). Platform-gated: a package of this kind only appears in the wizard when the relevant screen reader is available on the host.
For the initial supported package set, RABBIT should implement these unattended strategies:
- REAPER Windows standard install:
- download the official installer,
- verify signature and version,
- invoke it itself with unattended arguments for standard installation,
- wait for completion and treat non-zero or unexpected exit codes as failure,
- verify
reaper.exeand the target resource path after completion.
- REAPER Windows portable install:
- either invoke the official installer itself with unattended portable-install arguments or use another validated vendor-supported unattended method,
- wait for completion and treat non-zero or unexpected exit codes as failure,
- verify both
reaper.exeandreaper.iniin the selected portable folder.
- REAPER macOS standard install:
- download the official disk image or app distribution,
- verify signature/notarization,
- mount or extract it non-interactively,
- copy/install REAPER unattended into
/Applicationsor the chosen target, - verify the final app bundle and version.
- REAPER macOS portable install:
- create the portable folder layout unattended,
- place the REAPER app bundle there using a verified unattended copy flow,
- create or preserve
reaper.inias required for portable mode.
- OSARA:
- install unattended by either invoking a validated silent installer path or reproducing the upstream file layout directly into the selected REAPER resource path,
- manage the keymap behavior as a RABBIT choice: replacement plus backup when it loses nothing of the user's, keep otherwise, and either one on request.
- SWS:
- install unattended by placing the correct verified binary into
UserPluginsfor the selected REAPER architecture.
- install unattended by placing the correct verified binary into
- ReaPack:
- install unattended by placing the correct verified binary into
UserPluginsfor the selected REAPER architecture. - mark the package with
requires_user_acknowledgement = true. Whenever a RABBIT run would install or update ReaPack, the wizard must show a dedicated confirmation page before the Review step, and the CLI must prompt before staging the artifact. The page reproduces the donation hint visible on https://reapack.com/ in the active locale: ReaPack is free software released under the terms of the LGPL, but its author Christian Fillion accepts donations at https://reapack.com/donate to support continued development. The page links to the donation URL, states clearly that donating is optional and that no donation is required to use ReaPack or RABBIT, and only enables Continue once the user has explicitly acknowledged the notice (a checkbox or focused button in the GUI; an interactive prompt or--accept-reapack-donation-noticeflag in the CLI for unattended runs). Skip the page entirely on runs where ReaPack is neither being installed nor updated.
- install unattended by placing the correct verified binary into
- ReaKontrol:
- install unattended by placing the correct verified binary into
UserPluginsfor the selected REAPER architecture or platform, - preserve existing
reaKontrol/fxMapsuser mapping data and treat it as user content, not package-owned files.
- install unattended by placing the correct verified binary into
- JAWS scripts (Windows only):
- latest-version + artifact provider: HFS REST API at
hoard.reaperaccessibility.com. RABBIT callsPOST /~/api/get_file_listwith the JAWS-Scripts directory as the path and parses the returned JSON to pick the newest archive (date + filename contain the version anchor). Source archive URLs come from the same API. - install unattended by extracting the archive and placing the script set
into the user's JAWS settings folder (
%APPDATA%\Freedom Scientific\JAWS\ <version>\Settings\enufor the highest installed JAWS version, falling back to a clearly reported error if no JAWS install is detected). - the package only appears in the wizard package list on Windows when JAWS is detected on the host. macOS users never see the JAWS scripts row.
- back up any existing same-named script files before overwriting; track the install through the standard RABBIT receipt mechanism.
- latest-version + artifact provider: HFS REST API at
- FFmpeg (Windows only, opt-in):
- latest-version provider: Gyan.dev's
*.verplain-text endpoint athttps://www.gyan.dev/ffmpeg/builds/ffmpeg-release-full-shared.7z.ver, a single line of UTF-8 with the current stable release version. - artifact provider fans out per architecture:
- x64 → Gyan.dev's
ffmpeg-release-full-shared.7zredirector. The URL is fixed; the version pulled from the*.verendpoint is the authoritative version stamp. - ARM64 / ARM64-EC → highest stable tag from
tordona/ffmpeg-win-arm64's GitHub releases (skipping thedaily-autobuild-…/latestrolling tags) whose major matches the supported FFmpeg major; assetffmpeg-<ver>-full-shared-win-arm64.7z.
- x64 → Gyan.dev's
- install unattended by extracting every file under the archive's
bin/folder into the selected REAPER resource path'sUserPlugins(skippinginclude/,lib/,doc/, …). The user's FFmpeg-aware plugins (REAPER's video decoder) load from the same folder. A single RABBIT receipt records every extracted file so future detection rounds-trip cleanly. - opt-in by default (
recommended = false); doesn't surprise users who don't need video decoding. - macOS is filtered out at the manifest level until a scriptable
shared-
dylibsource materializes. OSXExperts.net and evermeet.cx ship static binaries only, which can't satisfy REAPER's video decoder. - external-install detection prefers spawning
<UserPlugins>/ffmpeg.exe -version(with theCREATE_NO_WINDOWflag on Windows so users don't see a console flash) and parsing the first stdout line; falls back to the libavformat-major filename heuristic when no executable is present.
- latest-version provider: Gyan.dev's
Configuration steps are post-install actions that run after the package install pipeline finishes, typically to wire newly-installed packages into REAPER's per-target config files. They are manifest-driven so future steps can be added without rewriting the engine.
ConfigurationStep {
id,
display_name_key,
display_description_key,
recommended,
requires_package_id, // dependency package id, or None
kind // tagged enum of step kinds (see below)
}
Initial step kinds:
AddReapackRemote { name, url }: append a remote into ReaPack's<resource>/reapack.ini[remotes]section. Idempotent on URL — re-running is a no-op when the URL is already listed; the appended index honours ReaPack'ssize=field so it lands at the next slot ReaPack itself would have written.
The single shipped step today is the REAPER Accessibility ReaPack
remote (https://github.com/Timtam/reapack/raw/master/index.xml),
recommended when ReaPack is part of the install plan or already on
disk.
Wizard surface:
- Configuration steps appear in their own "Configuration" group at
the top level of the Packages tree, sibling to the "Packages"
group. Each step's row label is its localized display name; rows
whose dependency package isn't installed or queued show
(requires <package>)and rows whose effect is already on disk show(already applied). Both states render the row as disabled with the checkbox forced unchecked, and click/Space input on those rows is pre-empted before native processing reaches the TVS_CHECKBOXES auto-cycle so screen readers don't announce a phantom toggle. - Toggling the dependency package live (e.g. unticking ReaPack) re-evaluates the configuration row's availability and, if the row becomes actionable again, restores its recommended-default tick.
- The row's accessible description and the wizard's details pane carry the longer "Unavailable: requires X to be installed." / "Already applied on this REAPER target." sentence so the user hears the full reason on focus.
CLI surface:
rabbit setupaccepts--config-step <id>(repeatable allowlist) and--skip-config-step <id>(skip-list overlaid on the recommended-default set). With no flags, every recommended step whose dependency is satisfied and which isn't already applied runs automatically.apply_configuration_stepreturns a per-step report whose status is one ofApplied,Skipped,SkippedDependencyMissing, orDryRun; the report stitches into the sameSetupReportJSON the package install pipeline writes.
Detection:
- "Already applied" detection is per-
kind. ForAddReapackRemote, RABBIT scans the[remotes]section of<resource>/reapack.inifor an entry whose URL field matches. Missingreapack.inireads as "not applied". The detection is cheap enough to run during model build and after every target reselection, so the wizard's "(already applied)" tag stays in sync with whichever target the user picks.
Resource path layout:
<resource_path>/
reaper.ini
reaper-kb.ini
UserPlugins/
KeyMaps/
ReaPack/
registry.db
reaKontrol/
fxMaps/
osara/
locale/
RABBIT/
install-state.json
logs/
backups/
Extension files:
- OSARA Windows: install all available supported OSARA DLLs, matching the
upstream installer behavior:
UserPlugins/reaper_osara32.dllUserPlugins/reaper_osara64.dllUserPlugins/reaper_osara_arm64ec.dllwhere supported
- OSARA macOS:
UserPlugins/reaper_osara.dylib
- SWS:
- install the binary matching the selected REAPER architecture, unless the upstream package explicitly supports installing multiple side-by-side architecture files.
- ReaPack:
- install the binary matching REAPER architecture, not merely the operating system architecture.
- ReaKontrol Windows:
UserPlugins/reaper_kontrol.dll
- ReaKontrol macOS:
UserPlugins/reaper_kontrol.dylib
- ReaKontrol support data:
- preserve
reaKontrol/fxMaps/and any user-created map files during install and update.
- preserve
- FFmpeg Windows (x64 and ARM64; macOS not yet supported):
- every file under the upstream archive's
bin/directory is flattened intoUserPlugins/. For a current Gyan / tordona FFmpeg 8.x build that'savcodec-62.dll,avdevice-62.dll,avfilter-9.dll,avformat-62.dll,avutil-60.dll,postproc-58.dll,swresample-6.dll,swscale-9.dll,ffmpeg.exe,ffprobe.exe,ffplay.exe. Keeping the executables alongside the libs lets the detection pass invokeffmpeg.exe -versionfor the authoritative release version on subsequent runs.
- every file under the upstream archive's
- Discover installation candidates.
- Detect current component state.
- Refresh latest-version metadata from providers.
- Build an install plan.
- Show the plan and require confirmation.
- Download artifacts into the RABBIT cache:
- Windows:
%LOCALAPPDATA%\RABBIT\cache - macOS:
~/Library/Caches/RABBIT
- Windows:
- Verify artifacts:
- HTTPS only.
- SHA-256 when known.
- Authenticode signature for Windows executables and DLLs where available.
- macOS code signing/notarization checks where available.
- Ensure REAPER is not running.
- Create backups.
- Apply changes unattended:
- invoke verified silent REAPER install steps where required,
- launch installer executables or equivalent package routines directly from RABBIT where the package model says so,
- copy verified extension files directly where possible,
- use temp files and atomic rename where possible.
- Write receipt and report.
- Verify the final installed state against the plan and report any mismatch as an installation failure, not a silent warning.
- If REAPER is running, stop before changing extension files and ask the user to close it.
- When OSARA is selected, back up
reaper-kb.iniand replace it with the OSARA key map by default only when OSARA is new orreaper-kb.inistill matches the installed OSARA key map; otherwise keep it, and point at OSARA's "Merge OSARA key map" action. The user can override either way with the Packages checkbox or--replace-osara-keymap/--preserve-osara-keymap. - Do not overwrite or delete user-created
reaKontrol/fxMapscontent during a ReaKontrol install or update. - Back up every overwritten file under
RABBIT/backups/<timestamp>/. - Keep a machine-readable operation report and a plain text report.
- Treat non-writable targets as a planning error before downloading anything.
- Do not request elevation unless the selected REAPER app install target requires it.
- Do not delete unknown files during update. Only remove files listed in a RABBIT receipt or explicitly owned by the package manifest.
- Closing the window during an install stops the run; it does not abandon it. Ask first, with No as the focused button, then let the pipeline stop at its next package boundary so every guard unwinds the way it does on a clean finish: the install lock is released, extraction temp dirs are removed, and the run writes a report saying which packages landed and which were never reached. Whatever step is running when the user confirms runs to completion — an elevated vendor installer has no halfway point to return to — so the wizard says it is finishing that step rather than pretending the stop is instant.
- Refuse to close at all while RABBIT is replacing its own program files. That swap has no unwind path, so there is no answer that makes quitting safe; say so instead of offering a choice that cannot be honoured.
Use message IDs from the first commit. Recommended Rust-side choice: Fluent via
fluent-rs. Required built-in locales should be embedded into the executable.
During development and for advanced overrides, RABBIT may also read locale files
like:
locales/
en-US/
rabbit.ftl
Rules:
- No string concatenation for user-visible messages.
- The default release must work without a
locales/directory. - Include translator comments for placeholders.
- Localize logs that are shown to users, but keep an internal structured event code for support.
- Include accessible names, descriptions, dialog titles, and button labels in localization.
- Keep package display names localizable, but package IDs stable and untranslated.
Cargo.toml
crates/
rabbit-core/
rabbit-platform/
rabbit/ # the single user-facing binary (CLI + GUI dispatch)
ui/
wxdragon/
xrc/
locales/
en-US/
de-DE/
fr-FR/
it-IT/
docs/
architecture/
tests/
rabbit-core has no GUI dependency. rabbit-platform isolates Windows/macOS
APIs. The rabbit binary crate depends on both and contains:
cli/— the clap-based subcommand parser (formerrabbit-clicontent).ui/— the wxDragon wizard (formerrabbit-ui-wxdragoncontent), behind aguiCargo feature for dev-loop builds that skip native deps.main.rs— the argv dispatcher that picks GUI or CLI mode.
This layout lets another native UI shell replace the wxDragon module without
touching the package engine. Files under locales/ and ui/ are
source/development assets; release builds embed required resources instead
of shipping those directories beside the executable.
Automated tests:
- manifest parsing
- version comparison
- path discovery from fake filesystem fixtures
- ReaPack SQLite registry parsing
- receipt read/write
- install planning
- backup and rollback
- embedded-resource availability without external files
- release packaging checks for accidental runtime file dependencies
- GitHub Actions workflow validation for push builds and tagged releases
- release-manifest generation and checksum publication
- RABBIT self-update version comparison and channel selection
- self-update staging, verification, rollback, and restart handoff logic
Manual accessibility tests:
- Windows 11 with NVDA
- Windows 11 with Narrator
- Windows 11 with JAWS before beta
- macOS current release with VoiceOver
Install tests:
- clean Windows standard install
- clean Windows portable install
- clean macOS standard install
- clean macOS portable install
- update from older REAPER plus older extensions
- unattended REAPER Windows standard install end-to-end
- unattended REAPER Windows portable install end-to-end
- unattended REAPER macOS standard install end-to-end
- unattended REAPER macOS portable install end-to-end
- unattended OSARA install end-to-end
- unattended SWS install end-to-end
- unattended ReaPack install end-to-end
- unattended ReaKontrol install end-to-end
- GitHub Actions push build produces downloadable Windows and macOS artifacts
- GitHub release workflow publishes release assets, checksums, and update metadata
- launch RABBIT from a temporary folder with no neighboring resource files
- existing user key map preserved
- OSARA key map replacement with backup
- ReaPack already installed with populated registry
- existing
reaKontrol/fxMapsuser maps preserved - extension installed manually with unknown version
- RABBIT self-update from one released version to the next on Windows
- RABBIT self-update from one released version to the next on macOS
- Select and validate the exact unattended invocation strategy for the REAPER Windows installer for both standard and portable targets, including exit codes, logging, and upgrade behavior.
- Select and validate the exact unattended install strategy for REAPER on macOS: mounted DMG copy flow, packaged installer flow, or another vendor-supported non-interactive path.
- Confirm SWS and ReaPack macOS binaries expose reliable version metadata outside ReaPack's registry DB. If not, RABBIT receipts and ReaPack DB should be treated as the reliable sources.
- Confirm whether ReaKontrol release binaries expose reliable version metadata on Windows and macOS. If not, RABBIT receipts plus package-file presence should be treated as the reliable sources.
- Decide whether the RABBIT update feed should be a GitHub release asset JSON
generated by
release.yml, a repository-hosted appcast/manifest file, or both. - Validate the exact Windows self-update replacement mechanism for a running single executable: temporary helper executable, script, or another minimal relaunch approach.
- Validate the exact macOS self-update replacement mechanism for a signed and notarized app bundle without breaking code signing, quarantine, or app path stability.
- Decide how stable and beta RABBIT release channels should be represented in the GitHub release/update metadata and in the UI.
- Decide whether first-version RABBIT should install SWS directly from SWS release assets or through an unattended ReaPack-driven path after ReaPack is present. The design target remains unattended either way.
- Build a small wxDragon proof of concept and test it with NVDA, Narrator, and VoiceOver before expanding it into the full wizard.
- Verify whether wxDragon exposes the wxWidgets accessibility hooks RABBIT needs directly. If not, document the smallest upstream contribution or local wrapper needed for accessible names, descriptions, roles, and state.
- Verify wxDragon/wxWidgets release packaging on Windows and macOS can meet the one-download, no-RABBIT-installer goal without sacrificing code signing, notarization, or screen-reader behavior.
- Add a Windows-side live-upstream smoke pipeline analogous to
macos-smoke.yml: download FFmpeg per arch (Gyan x64, tordona ARM64), extract thebin/payload into a temp UserPlugins, assert the receipt round-trips, and round-trip the detection back to the upstream version. Until that lands, FFmpeg's per-arch resolver is exercised only by unit tests against fixture release-list bodies, not against real GitHub / Gyan responses. - Find a scriptable source of shared (
dylib) FFmpeg builds for macOS so the FFmpeg row can be enabled there too. OSXExperts.net and evermeet.cx ship static binaries only, which can't satisfy REAPER's video decoder. Candidate fallbacks include bridging to Homebrew (detectbrewon$PATHand runbrew install ffmpegon opt-in) or hosting our own shared builds.