SoundCraft
Audit basis: this checkout is tag v0.16.0, commit db51dd17398852ba70919c5a560d1c8ed9e3e6c6 (shallow clone of the release tag; the v0.15.0 ref was fetched for id diffs). The installed /Applications/SoundCraft.app reports version 0.16.0, and its binary prints SoundCraft 0.16.0 (macos aarch64), so the bundle matches this source. Verify against your installed version if the ArtCraft Launcher has auto-updated since. Everything below was measured statically from this tree: no build, no GUI launch, no audio device was exercised.
v0.15.0 → v0.16.0 adds view.zoom_toggle_cancel (Cancel Zoom Toggle — Alt+Shift+E or Alt-click keeps the current view, PR #1101) — one new command, total command specs 483 → 484 — and removes no id. Behaviour: the Clip menu acts on the whole edit selection when the right-clicked clip is part of it (#1196); Mix clamps clip-FX gain and send-level automation (#1126); transport.play {from} plays at the requested position, not the selection (#1075); range_param defaults the range start to the selection start (#1214); AutoParam::parse keeps plugin parameter-id case (#1227); and a hardening wave bounds automation-lane value_at (#1215), GridValue::step_samples (#1216), TempoMap bar math (#1220), non-finite remove_dc/RMS (#1221/#1222), CAF cookie lengths (#1200), drop-frame timecode labels (#1201), WAV byte rates (#1202), FLAC vendor strings (#1211), MIDI-import tempo/track floods (#1212) and H.264 POC/DPB saturation (#1226/#1229). MCP tools (17) and control methods (17) are unchanged — zero diff files under those trees. ⚠️ The previous audit credited the Zoom Toggle cancellation to v0.15.0 — compare-log tail trap; the view.zoom_toggle_cancel registration exists only at v0.16.0.
v0.15.0 was a hardening release with no command-registry change: what landed there was send-fader moves writing send-level automation (PR #1146; send-level automation exists in crates/mix at the v0.15.0 tag), the CLI script --keep-going exit status reporting script failures, the MCP server answering empty batches and non-object messages with a JSON-RPC error instead of silence, .scgrp clip-group files refusing absolute audio paths, Print Score/MusicXML output byte-budgeting, and overflow/hardening fixes (VST3 bus-layout limits among them).
Overview
SoundCraft is an open-source, pure-Rust digital audio workstation: a clean-room reimplementation of the Avid Pro Tools workflow (recording, editing, mixing, automation, bounce) that also runs in a browser (README.md, docs/target-app-parity.md). The parity target is Pro Tools Ultimate 2026.4.1. It is a Cargo workspace of 14 crates plus three entry points — the desktop app (egui 0.37 this release), soundcraft-cli (parsed with clap following the repo's RFC-0012), and a WebAssembly build. It is pre-alpha: the repo's own generated report counts 397/512 target menu leaves implemented by the engine (77.5 %, docs/parity-checklist.md) and the alpha gate still lists failing workflows — interface recording, MIDI recording, session interchange (docs/roadmap.md "Alpha gate"). Source: github.com/storytold/soundcraft.
Capabilities (verified)
The command layer is the API (start here)
- 484 engine command specs at this tag, from the 31 production modules registered by
command_specs()(crates/engine/src/cmd.rscommand_specs).- Breakdown (re-counted at v0.16.0): 389 literal
cmd!ids in non-test engine sources (was 388 at v0.15.0; +view.zoom_toggle_cancel, none removed) + 94 generated by four local helper macros —toggle!17,flag!61,radio!6,option!10 — + 1 directCommandSpec(mix.insert_state) = 484. ⚠️ The previous ledger printed 482 from "397 literal" (a scope that included test-file registrations) while its own sum omitted the 10option!ids; 484 is the reproducible non-test decomposition. Count your build with the CLI rather than any static number. - Each spec carries id, label, menu path, shortcut, params doc, enabled reason, journal/undo flags and a run function. Counting textual
cmd!(occurrences overcounts macro-definition/doc/test lines and misses the 94 generated ids — derive the count from the id literals.
- Breakdown (re-counted at v0.16.0): 389 literal
- 67 UI commands (windows, dialogs,
ui.dock,ui.dock.reset,ui.theme,ui.audio_device,ui.set,window.*,view.mix_section,view.scroll_into_view) live in the UI crate'sUI_COMMANDS(moved modules in the refactor; count carried from v0.13.1). The desktop control channel appends them toengine.commands, so a running app reports 551 ids;soundcraft-cli commandsand the headless MCP server report 484. No id overlaps the two sets. - CLI (
soundcraft-cli, 10 subcommands +--version/--help; arguments are now parsed with clap following RFC-0012, PR #1136 — same surface, standard clap usage errors for unknown flags):info FILE;convert IN OUT [--bit-depth 16|24|32f] [--rate HZ] [--normalize] [--dither|--no-dither];run [--in S.scraft | --demo] [--cmd ID[=JSON]]… [--bounce OUT] [--start T --end T] [--save S.scraft] [--inspect];script FILE [--in S | --demo] [--save S] [--bounce OUT [--start T --end T]] [--keep-going](--keep-goingnow reports script failures in the exit status — a script that kept going past errors still exits non-zero; fixed this release);commands [FILTER];describe ID;app [--port P] METHOD [JSON];mcp [--connect PORT] [--demo] [--automation-read-root DIR]… [--automation-write-root DIR]…;parity [--write PATH];plugins.- Carried behaviour: every flag accepts
--flag=value;run,scriptandconvertreject unknown options and missing values;--cmd=ID=JSONinline;--bouncewith no--start/--endbounces the whole session;convertdithers only when resolution is lost unless--dither/--no-dithersays otherwise. appshorthand: a dotted command id is wrapped asengine.execute; accepted control methods stay methods. Caveat:ui.scrollandui.zoomare not in that whitelist, sosoundcraft-cli app … ui.scroll/ui.zoomis misrouted; send those two over the raw TCP channel.
- Carried behaviour: every flag accepts
- MCP over stdio (
crates/automation/src/mcp.rs): protocol2025-06-18(accepts2025-03-26,2024-11-05); 17 tools, unchanged. Core:list_commands,execute,batch,inspect_session,new_session,open_session,save_session,import_audio,bounce_mix,parity. App-only (need the desktop app plusmcp --connect):screenshot,ui_inspect,ui_set,menu_invoke,click,drag,key. Resources:soundcraft://sessionandsoundcraft://commands.batchruns up to 1000 calls (MAX_BATCH_CALLS); larger arrays are rejected before anything runs. Any failed call makes the tool resultisError: true;keep_goingstill runs the rest. Malformed envelope input (empty batch, non-object message) gets a proper JSON-RPCInvalid Requestreply (fixed this release).- Tool schemas are a subset:
new_session/open_session/save_session/import_audio/bounce_mixforward their arguments to the engine command, so extra engine params work. Verify withdescribe.
- Desktop control channel:
soundcraft --control <port>orSOUNDCRAFT_CONTROL_PORT; newline-delimited JSON over TCP on127.0.0.1, one reply per line. 17 canonical methods (crates/ui-egui/src/control.rs):engine.execute(aliascommand),engine.commands,engine.parity,session.inspect(aliasdocument.inspect),ui.inspect,ui.menu.list,ui.menu.invoke,ui.set,ui.move,ui.click,ui.drag,ui.scroll,ui.zoom,ui.key,ui.text,ui.screenshot,app.quit.ui.dock,ui.dock.reset,ui.themeandui.audio_deviceare UI commands, invoked throughengine.execute, not top-level methods.ui.screenshot {path?}needs a presented frame and fails with "no frame was presented (is the window visible?)".- Two UI commands refuse a direct call and name the replacement:
ui.new_tracks_dialog("calltrack.newwith parameters") andui.bounce_dialog("callfile.bounce_mixwith a path"). - Offscreen UI, no window:
cargo run -p soundcraft-ui-egui --example ui_shot -- out.png [script.jsonl] [--blank] [--size WxH].
- Path confinement is MCP-only:
--automation-read-root/--automation-write-rootconfine every path for the in-process MCP server; each flag may be repeated, a kind left out grants no access of that kind, roots must exist, and--connectwith roots is refused. The desktop control channel has no equivalent confinement.
Editing and arrangement
- Edit window with tracks/clips/waveforms; Mix window (also as a separate native OS window through
window.mix_separate); movable/dockable panels Tracks/Groups, Clips, MIDI Editor, Memory Locations, Undo History — Tracks/Groups and Clips now dock as full-height columns (crates/ui-egui/src/docking.rs, PR #1088). - Five edit modes Shuffle, Slip, Spot, Grid, Grid-Relative; seven tools Zoom, Trim, Selector, Grabber, Scrubber, Pencil, Smart.
- Fades/crossfades in five shapes; cut/copy/paste/duplicate/repeat/shift/insert-silence/separate/heal/consolidate/strip-silence/nudge; Tab to Transient; Zoom Toggle; loop, quantize-to-grid, clip gain and gain envelope, clip effects, edit locks, colour, ratings.
- Strip Silence has three modes:
edit.strip_silence {…, mode?: strip|extract|separate, name?, number?, zeros?, suffix?};edit.strip_silence_preview(query) returns the padded ranges it would keep. Closing the Strip Silence window while the Mix view shows no longer leaves a stuck rectangle scan (fixed this release). - Clip Looping:
clip.loop {clips?, count?, length?, fill?};clip.unloop {mode?: remove|flatten}. - Clip List › Auto Rename:
clip.auto_rename {clips?, name?, number?, zeros?, suffix?}sets the names editing gives the clips it separates; the schemes live in the session and survive save/reopen. - Playlists with comping lanes, clip groups (
.scgrp), Clip List, track folders, VCA masters, track freeze/commit/bounce, file-based track presets and Import Session Data..scgrpimport now rejects audio paths that are absolute or contain..(hardening this release). track.commitkeeps the track's exactChannelFormat, surround/height/ambisonic included, up to the renderer's 16 channels.- Commands Keyboard Focus single-key editing in the Edit window;
options.keyboard_focus {commands|clips|groups|none}. - Undo/redo for document commands, an undo history window, and
engine.historyreturning{undo, can_redo}.
Mixing, automation and plug-ins
- 10 inserts and 10 sends per track, busses, aux inputs, master faders, VCAs, routing folders, object/bed routing, solo modes, mute/solo groups, phase invert, input trim, pre/post sends, automatic plug-in delay compensation. Aux and Folder strips are ordered by exact acyclic routing depth.
- 30 built-in plug-ins in
REGISTRY: 27 processors + 3 instruments (synth, drum synth, sampler; incl.auto_pan,ring_mod,subharmonic). Auto Pan now keeps the stereo image (fix this release).engine.plugins/soundcraft-cli pluginslist them. - Offline AudioSuite processing via
audiosuite.process {process, params?, clips?, tracks?, start?, end?}: any built-in plug-in id plusnormalize|reverse|invert|gain|duplicate|time_stretch|pitch_shift|varispeed|speed_ramp|signal_generator(10 named processes). - Automation: lanes for volume, pan, mute, send level/pan/mute and any insert parameter; seven modes; moving a send fader now writes send-level automation (fixed this release, PR #1146);
automation.set_point,write_range,clear,thin,thin_all,write_to_current,write_to_all,volume_to_clip_gain, plus coalesce commands. Mute automation is evaluated per sample inside a render block. - Third-party hosting in-process: CLAP, VST3 and macOS Audio Units. Discovery:
engine.clap_plugins {rescan?},engine.vst3_plugins {rescan?}; idsclap:<id>,vst3:<class id hex>,au:<type>:<subtype>:<manufacturer>. There is no Audio Unit discovery command — the UI scans AUs at menu time. - Plug-in editors: CLAP opens the plug-in's own floating window (Windows hosted-embedded), VST3 editors on macOS and Windows, Audio Units never; on the signed macOS build third-party VST3 is refused (library-validation entitlement).
- Plug-in presets are partly UI-only; for a hosted plug-in's opaque state use
mix.insert_state {track, slot, state: base64|null}— not undoable and not journaled.
Recording and audio devices
- Record arm, input monitoring, punch on selection or on the fly, pre/post-roll, loop recording with a playlist per take, destructive and track-punch modes.
- Takes stream to disk while recording: one WAV per take, the header rewritten every second; after stop the take is decoded into RAM as a session source.
- Track input routing exists:
track.input {"input":"In 3"};plan_takesrecordstrack.channels()consecutive device channels. What is missing is an input/output matrix with per-channel gain/delay and latency reporting. - Device selection is real:
ui.audio_device {system?, output?, input?, sample_rate?, buffer_size?, list?}changes the audio system/device/rate/buffer and reopens the player; it refuses while recording.setup.playback_engineis a different, legacy engine command whose settings playback never reads. ASIO is behind the opt-inasiobuild feature. - Autosave on its own thread after changes, one folder per session, plus crash recovery at launch;
Backups/beside a session keeps the newest ten timestamped copies on overwrite.
MIDI, notation, instruments and time
- Instrument and MIDI tracks, piano-roll editor with velocity lane and event list, note add/edit/delete/move, quantize, input quantize, step input, transpose, real-time properties, MIDI track offsets, retrospective record.
- Standard MIDI File: reads formats 0 and 1 fully and format 2 best-effort; always writes format 1.
mix.sampler_load {track?, path, params?}/mix.sampler_clearfor the built-in Sampler.- Score Editor, MusicXML export (
file.export_sibelius,file.send_to_sibelius), printable SVG score (file.print_score). - Monophonic audio-to-MIDI (
edit.copy_audio_as_midi,track.extract_midi) and chord detection to markers. - Five timebases; tempo and meter maps with ramps; key signatures; Identify Beat; Beat Detective; Elastic Audio warping.
- No MIDI hardware I/O at all:
setup.midi_*only store settings.
Audio and session formats
- Read: WAV (PCM 8/16/24/32, float 32/64, extensible, RF64/BW64, BWF, unfinalised recordings) and AIFF/AIFF-C natively; FLAC, MP3, Ogg Vorbis, AAC/ALAC in MP4/M4A/M4B, CAF, Matroska and ADPCM/A-law/µ-law via symphonia 0.6. Format is detected from bytes first.
- Write:
wav, aif, aiff, flaconly (ENCODE_EXTENSIONS), with optional TPDF dither; WAV switches to RF64 above 4 GiB. Float32 WAV and AIFF-Cfl32keep finite samples above full scale. - Waveform overviews are generated in memory, not cached as
.wfmfiles. - Native session
.scraft: pretty-printed serde JSON withformat_version1; a newer version is refused;from_jsonsanitises and validates (duplicate ids and an exhausted id space are rejected). Audio that only exists in memory is written as 32-bit float WAV into a siblingAudio Files/folder; saves are atomic; an overwrite copies the old file toBackups/first. There is nodeny_unknown_fields, so unknown JSON keys are ignored by serde and dropped when the app next saves. .scraftzis the browser bundle (zip of the.scraftplusAudio Files/, 10 000-entry / 1 GiB caps). The desktop app does not open it.- Stored media paths are resolved by
craft_docpath.resolve_absolute: a stored path is followed only when local or on the session's own network share. .scgrpclip groups are JSON plus a<name> Audio/folder of 32-bit float WAVs.- One session per running app; there are no session tabs.
Export, bounce and delivery
file.bounce_mix {path, format?: wav|aiff|flac, bit_depth?: 16|24|32f, start?, end?, source?: main|bus name, normalize?, dither?, fold_down?: stereo}streams the render to disk and returns{path, bytes, seconds, peak_db, lufs, true_peak_db};ditherdefaults true,normalizefalse, omitted range means the edit selection else the whole content. Bounce is about 20 % faster this release with byte-identical output (PR #1144).file.bounce_stems {dir, format?, bit_depth?, start?, end?, dither?, fold_down?}writes one file per unmuted, active audio/instrument/MIDI track.file.export_clips {dir, clips?, format?: wav}writes clips as WAV only;file.export_midi {path, tracks?},file.export_session_text {path?, replace?},file.export_selected_tracks_as_session,file.export_sibelius/file.send_to_sibelius,file.print_score,file.export_clip_groups.session.save_template {path, replace?}writes a clip-stripped.scraft; there is no template browser.
Video, surround and platforms
- Video track with thumbnails, Video window with optional timecode burn-in, Video Universe strip; pure-Rust decoding of H.264 (8-bit 4:2:0), Apple ProRes (422 family, 4444/XQ) and Motion JPEG. HEVC, AV1 and DNx movies are recognised by the demuxer but frames return "unsupported". Container/bitstream layers are shared craft-libs code (
craft_media::isobmff,craft_media::bitstream). - Surround/immersive mixing: 34 main/bus format choices from Mono to 9.1.6 and 1st–7th Order Ambisonics;
setup.main_format; surround panners;track.objectfor object/bed routing; Renderer window. - Native builds for macOS (universal, signed/notarized), Windows x64/x86/arm64 (per-user install by default now), Linux (AppImage, deb, rpm, Flatpak, tar.gz, riscv64 tarball; XWayland drag-and-drop by default on Wayland), FreeBSD, and WebAssembly. The web build has no TCP control channel and no filesystem.
- Startup update prompt with direct self-updating (craft-update).
Known limitations and not-implemented
Do not assign these; each is absent or partial at v0.16.0:
- MIDI hardware I/O is absent. No recording from a keyboard, no live playing through instruments, no MIDI out, clock or MTC.
- No Pro Tools interchange. No
.ptx/.ptf, AAF, OMF or Media Composer session import/export; the nearest bridge isfile.import_session_databetween SoundCraft.scraftsessions. - Audio-interface depth. Input and output are separate cpal streams; the mix runs in fixed 512-sample blocks; no duplex clock, no I/O matrix, no latency reporting, no record-offset compensation.
- All audio sources are decoded whole into RAM. No disk streaming for playback; bounces themselves stream to disk.
- Plug-in limits. AAX is not hosted. The signed macOS build refuses third-party VST3 (library-validation entitlement). AU editors are not hosted and AUs have no discovery command; CLAP embedded editors only on Windows; VST3 editors only macOS/Windows. No external sidechain, no ARA, no out-of-process sandboxing.
- No compressed export (MP3/AAC/M4A/Ogg/Opus) even though those decode on import.
- Video is decode-only and limited. No HEVC/AV1/DNxHD/DNxHR decode, no video export or bounce-with-video, no external timecode.
- No immersive delivery. No ADM BWF, Dolby Atmos renderer integration or binaural.
- No control surfaces (HUI/MCU/EUCON) and no external sync (MTC/LTC/video reference).
- English-only UI. No string catalog; a Hangul fallback font is appended for Korean names; no other fallbacks.
- Session management is thin. No template browser, no batch rename; the Workspace window is a one-folder file list.
- No speech-to-text (settings only) and no fidelity harness against Pro Tools.
.scraftzdoes not open on the desktop.- Parity is uneven by area. The generated report counts 397/512 menu leaves implemented (Window 1/52, AudioSuite 0/28, View 92/112, File 22/30). AudioSuite catalog leaves all map to the single
audiosuite.processcommand. - Docs still lag the code in places (alpha-gate input-device row, G-16 track-preset recall, the Hangul fallback denial). Trust the code paths cited here, then
soundcraft-cli describe.
How to operate
Launch on macOS
- GUI binary
/Applications/SoundCraft.app/Contents/MacOS/SoundCraft;open -a SoundCraft, oropen -a SoundCraft --args --demo. A terminal launch with--controlprints the control port on stdout. - App flags:
--demo/--sample,--no-audio(never arm or record in a smoke test),--control <port>(0= pick a free port and print it),--version/-V, and positional files:.scraftopens as a session,.mid/.midi/.smfimports MIDI, anything else imports as audio. - Environment:
SOUNDCRAFT_CONTROL_PORT,SOUNDCRAFT_CONFIG_DIR,SOUNDCRAFT_NO_PREFS(recommended for agent test runs),SOUNDCRAFT_NO_SYSTEM_FONTS,RUST_LOG. - Settings on macOS:
~/Library/Application Support/SoundCraft/—ui.json,Autosave/,Presets/,logs/soundcraft.log. Aportable.txtbeside the executable switches to<exe dir>/SoundCraftData. soundcraft-cliis not inside the app bundle: installsoundcraft-cli-<ver>-macos-universal.zipfrom the release, or build it. Check both versions before mixing them.
Document and window model
One session per app; session.new/session.open/session.close replace it. Programmatic session switches do not prompt to save — save first. Edit and Mix are separate views; window.mix_separate puts Mix in its own native window. There are no session tabs.
Positions, references and ranges
- Positions: a JSON integer (or float) is samples;
{"seconds": 2.5}is seconds; a string is parsed in the current main-counter format then all formats, optionally prefixed withbars_beats:,min_secs:,timecode:,feet_frames:orsamples:. CLI--start/--endparse a bare decimal as seconds. - Ranges:
start+end, orstart+length;startalone is a point range; both omitted = the edit selection. Tracks by id or name; clips by id; buses by case-insensitive name.
Open, import, save, export
- New/open:
session.new {name?, sample_rate?, bit_depth?: 24, template?: blank|demo};session.open {path}never fails on missing media (it warns);session.save {path?, replace?},session.save_as,session.save_copy,session.save_template,session.revert,session.close. - Import:
file.import_audio {path | paths: [..], track?, at?, new_tracks?},file.import_midi,file.import_video,file.import_clip_groups,file.import_session_data. - Export/bounce: see above. Always read the returned
path/bytes/levels; a completed call does not prove the audio is non-silent. - Audio device:
ui.audio_device {"list":true}returns{config, device, systems}; applying reopens the devices and refuses while recording. Save before changing devices.
Keyboard shortcuts (verified in code)
Space play/stop; Shift+Space half-speed; Cmd+Space or F12 record; F1–F4 edit modes; F5–F10 tools; Enter new memory location; Cmd+= Mix/Edit; Tab to transient; Cmd+Shift+N new tracks; Cmd+S/O/N save/open/new; Cmd+E separate; Cmd+D duplicate; Cmd+U strip silence; Cmd+Alt+L loop clip; Cmd+Z undo; Cmd+Shift+K export clips; Cmd+Alt+B bounce mix; Cmd+P print score; Cmd+1 Transport, Cmd+3 Big Counter, Cmd+4 Automation, Cmd+5 Memory Locations, Cmd+9 Video; Alt+Shift+C track commit; Cmd+Alt+[ / ] waveform zoom; Cmd+Ctrl+1–5 zoom presets; Cmd+Alt+0–5 clip rating; Cmd+W close window. The in-app Setup › Keyboard Shortcuts window (window.shortcuts) is the live list.
Recipes that work at this tag
sh# Headless: demo session → set a level → insert an EQ → bounce → print the session JSON. soundcraft-cli run --demo \ --cmd 'mix.volume={"track":"Kick","db":-6}' \ --cmd 'mix.insert={"track":"Bass","plugin":"eq_7band"}' \ --bounce mix.wav --inspect # Live app: control channel on a free port, no output device. /Applications/SoundCraft.app/Contents/MacOS/SoundCraft --demo --no-audio --control 7801 & soundcraft-cli app --port 7801 mix.new_bus '{"name":"Verb"}' soundcraft-cli app --port 7801 mix.send '{"track":"Bass","bus":"Verb","level_db":-12}' soundcraft-cli app --port 7801 automation.write_range '{"track":"Bass","param":"volume","start":0,"end":96000,"value":-6}' soundcraft-cli app --port 7801 file.bounce_mix '{"path":"mix.wav","source":"Verb"}' soundcraft-cli app --port 7801 ui.screenshot '{"path":"shot.png"}' # Named clips from Strip Silence, then preview the ranges without touching the session. soundcraft-cli run --in song.scraft --cmd 'edit.strip_silence_preview={"tracks":["Vox"]}' soundcraft-cli run --in song.scraft \ --cmd 'edit.strip_silence={"tracks":["Vox"],"mode":"strip","name":"VOX","number":1,"zeros":2}' \ --save song.scraft --inspect # Give an MCP client a headless DAW confined to two read folders and one output folder. claude mcp add soundcraft -- soundcraft-cli mcp --demo \ --automation-read-root ./project --automation-read-root ./samples \ --automation-write-root ./out
mix.insert takes a built-in id from engine.plugins (or a clap:/vst3:/au: id); mix.send needs the bus to exist. All positions in these examples are samples.
Discover the build you are talking to
soundcraft-cli commands <filter> lists ids/labels/menu paths; soundcraft-cli describe ID prints the authoritative parameter doc; over the control channel use engine.commands {filter} and session.inspect; over MCP use list_commands and inspect_session. Labels, menu paths and shortcuts can change between releases — bind to ids.
Working with an AI agent
Legitimate, evidence-checkable work:
- Prepare and convert inputs.
soundcraft-cli info FILEprobes audio;soundcraft-cli convert IN OUTlands assets in WAV/AIFF/FLAC (output extension decides; anything else is refused). - Drive it headlessly with
soundcraft-cli run/script/mcp, or bridge MCP to a running app with--connect. Preferbatchfor many edits (cap 1000), theninspect_sessionandsession.audio_healthto verify. Most document commands are undoable; queries, view/session settings and the explicitly non-journaledmix.insert_stateare not. - Read and repair
.scraft. Pretty JSON withformat_version: 1: you may parse, diff and patch it, but never bump the version, and do not add private top-level keys. Keep ids unique per namespace. KeepAudio Files/paths relative to the session folder. Never edit a session while the app or CLI has it open. - Compose mix work from commands.
mix.new_busbeforemix.send;mix.insert {"plugin":"eq_7band"}thenmix.insert_params/mix.insert_param;mix.volume/pan/trim;automation.write_rangeorset_point;file.bounce_mix … source:"Verb"to bounce a bus.engine.pluginslists built-ins; AU has no query — know the fourcc id or use the UI. - Name clips from a batch edit.
clip.auto_renamebefore a cut/Strip Silence run gives every resulting piece a numbered name. - Verify exports.
file.bounce_mixreturnsbytes,seconds,peak_db,lufs,true_peak_db; check the file exists, has plausible duration and non-silent levels, then re-probe withsoundcraft-cli info. For a stem set, checkfilescount and each file. - Automate UI acceptance with the control channel and its UI commands. Run with
--no-audioand an isolatedSOUNDCRAFT_CONFIG_DIR; never arm a track, enable input monitoring or start recording in a smoke test. - What not to attempt: driving the GUI blind; promising AAF/OMF/
.ptx, MIDI-hardware recording/playback, MP3/AAC export, ADM/Atmos delivery or video export; opening.scraftzon the desktop; assumingsetup.playback_enginechanges the device (useui.audio_device); expecting Audio Unit discovery or AU editors; reading/copying Pro Tools resources — SoundCraft is clean-room (AGENTS.md).
Verification protocol
SoundCraft is pre-alpha and its docs lag the code in a few places. For any real task:
- Round-trip on a throwaway session first:
session.new→ one edit →session.saveto a scratch folder →session.openit back →file.bounce_mix→ confirm the returned levels are non-silent and the file exists. - Never trust a silent export: compare
peak_db/lufs/true_peak_dbwith expectations and re-probe the output withsoundcraft-cli info. - Back up and version per session: copy the whole folder (
.scraft+Audio Files/), not just the JSON;Backups/keeps the newest ten. - One session at a time, isolated profile: run agents with
SOUNDCRAFT_CONFIG_DIRpointing at a fresh folder. - Update apps only between projects: this skill is pinned to v0.16.0. Check
--versionbefore relying on a format or parameter detail. - Inspect, don't guess:
soundcraft-cli describe IDandengine.commandsgive the authoritative schema;session.audio_healthchecks loaded media without touching files.
Sources & evidence
- Repo: https://github.com/storytold/soundcraft — inspected at tag v0.16.0, commit
db51dd17398852ba70919c5a560d1c8ed9e3e6c6, release dated 2026-11-01; inspection date 2026-11-02; the v0.15.0 ref was fetched for id diffs. Installed app printsSoundCraft 0.16.0 (macos aarch64);CFBundleIdentifierai.storyteller.soundcraft. The bundle contains onlySoundCraft, notsoundcraft-cli. - Read:
README.md,Cargo.toml,apps/soundcraft/src/{main.rs,control_server.rs},apps/soundcraft-cli/src/{main.rs,args.rs,automation_args.rs},crates/engine/src/cmd.rs(registry) andcrates/engine/src/cmd/modules (incl.cmd/strip_silence.rs,cmd/setup_more.rs),crates/engine/src/{io.rs,autosave.rs,clip_group_file.rs,score.rs,file_access.rs},crates/model/src/{session.rs,mixer.rs,clip.rs,automation.rs,track.rs},crates/audio-io/src/,crates/dsp/src/{plugins.rs,plugins/,offline.rs,meter.rs},crates/midi/src/smf.rs,crates/mix/src/lib.rs,crates/playback/src/{lib.rs,record.rs,devices.rs},crates/video/src/{lib.rs,movie.rs},crates/automation/src/mcp.rs,crates/{clap-host,vst3-host,au-host}/src/lib.rs,crates/ui-egui/src/{control.rs,docking.rs,fonts.rs,menus.rs},crates/engine/catalog/menus.txt,docs/{mcp,control-protocol,gaps,parity-checklist,plugin-parity}.md. - Counts recomputed from source at this pin: 484 engine specs — +1 over v0.15.0's 482 (389 non-test literal
cmd!ids [+view.zoom_toggle_cancel] + 94 helper-macro ids [toggle 17 / flag 61 / radio 6 / option 10] + 1 direct struct; the previous ledger's 482 sum omitted the 10option!ids), 67 UI commands (count carried), 17 MCP tools / 2 resources, 17 control methods (2 aliases), 10 CLI subcommands (clap-parsed), 30 built-in plug-ins, 10 AudioSuite processes, 34 channel formats, 4 write extensions,FORMAT_VERSION = 1,MAX_BATCH_CALLS = 1000, 512-leaf menu catalog. Menu-parity 397/512 is the repo's generated report (unchanged). - Shared library pins from
Cargo.toml: allcraft-libscrates (craft-docpath,craft-media,craft-ui,craft-update) moved to revc5a1cbfb…this release (were92d392cf…+craft-updateat04aa1703…); egui fork stays6d518fc7…. - Evidence table:
evidence.mdnext to this file.


