Skip to main content

Utils (utils/)

Build, validation, and developer tooling for the Songbird Rust workspace. The directory is being migrated to a flatter convention: top-level entries are extension-less single-purpose drivers (build-rs, validate, export), and scripts grouped by concern live in subdirectories (utils/build/, utils/validation/, …). During the migration some entries exist in both locations — the top-level versions are the canonical ones to invoke; subdirectory scripts are the implementation pieces called by them.

Top-level drivers

EntryWhat it does
build-rsBoots the Vite dev server + Tauri shell with HMR. Default dev loop.
release-rsRelease-mode build of the desktop app (codesign, optional notarization).
validatePre-commit / pre-merge checks. Dispatches to validation/validate_*.sh. Steps: rust ts lint vitest.
exportInteractive master render — wraps songbird-cli render. Stems & lane variations are UI-only.
sync-typesRegenerate TypeScript bindings from Rust enums (ts-rs). Run after editing any sync defs.rs.
sync-docsSync README.md files into docs/ as Mintlify-flavoured .mdx.
worktreePopulate libraries/ submodules in this worktree by rsync from the core checkout.
submodulesWrapper around git submodule update --init --recursive (slower than worktree — prefer the latter).
install-hooksInstall the project’s git pre-commit hooks.

Subdirectories

PathContents
build/Platform-specific build scripts: build-android.sh, build-ios.sh, build-wasm.sh, build-web, release-wasm.sh, agent-headless.sh (headless DAW for browser testing).
validation/Per-language validators called by the top-level validate dispatcher: validate_rust.sh, validate_ts.sh, validate_lint.sh, validate_vitest.sh, validate_cpp.sh (vestigial — no C++ on this branch; safe to delete once confirmed unused).
server/Collaboration server: collab-server.sh (WebSocket server launcher), songbird-processor.js (legacy AudioWorklet code), songbird.service (systemd unit).
helpers/One-off Python helpers: convert_tracktion_state.py (Tracktion XML → bird), migrate_roopa.py (Roopa-format migration), midi-ping.py (MIDI device probe).

Common workflows

# First-time setup in a new worktree
./utils/workflow/worktree            # populate libraries/ from core
./utils/hooks/install-hooks       # set up git hooks

# Day-to-day dev
./utils/build-rs            # Vite + Tauri with HMR
./utils/validate            # all: rust + ts + lint + vitest
./utils/validate rust       # cargo test + clippy across the workspace
./utils/validate ts         # tsc --noEmit
./utils/sync-types          # after touching any sync engine defs.rs

# Headless harness for browser-driven E2E
./utils/build/agent-headless.sh

# Offline render
./utils/export                              # interactive: pick project + format
./utils/export song.bird --quick            # render with defaults
./utils/export song.bird --sample-rate 96000 --bit-depth 24 --normalize

Notes on export

The script wraps cargo run -p songbird-cli -- render and produces a master-mix WAV. It does not support stem export or take-lane variations from the command line — those run through the live audio graph and are exposed only via the desktop app’s Export menu (right toolbar → Export → Stems / Master + Take Lane Variations). If you need batch CLI stems in CI, the underlying limitation is that the offline render path (graph.process in a tight loop) doesn’t drive the clip scheduler. See rust/crates/engine/songbird-export/README.md for the full picture.

Migration status (utils/export vs utils/export.sh)

utils/export.sh is the historical name; utils/export is the new extension-less form matching build-rs, release-rs, etc. Both files currently hold the same script. Pick one to keep once the rename has propagated through any external callers (CI, docs, muscle memory).