Releases: shakfu/numchuck
numchuck
Python bindings for the ChucK audio programming language using nanobind.
The numchuck library provides interactive control over ChucK, enabling live coding workflows, bidirectional Python/ChucK communication, and comprehensive VM introspection—all while maintaining the existing real-time and offline audio capabilities.
Changes since the last Release
Added
-
OTF shred tracking (
session.py,common.py,repl.py,editor.py): Shreds added or removed via on-the-fly programming (chuck --add,chuck --remove) are now automatically tracked in the REPL and editor. A newsync_shreds()method onChuckSessiondiffssession.shredsagainstchuck.get_all_shred_ids()and reconciles: externally-added shreds appear in the topbar,?/shreds table, and status bar count; finished or externally-removed shreds are pruned. Sync runs on each render tick (via the bottom toolbar callback in the REPL, status bar callback in the editor), guarded by_otf_enableso there is zero cost when OTF is off. OTF-discovered shreds are tagged withshred_type="otf". -
OTF CLI flags (
cli/main.py,tui/tui.py,tui/repl.py,tui/editor.py,tui/common.py): Added--otfand--otf-portflags to thereplandeditsubcommands.--otfenables the ChucK OTF listener (default port 8888), allowing externalchuckcommands to add/remove shreds. The OTF port is shown in the REPL status bar when enabled. -
REPL real-time stereo level meters (
repl.py,waveform.py): Thewavecommand now displays live L/R peak meters below the shreds panel. Uses a background daemon thread pollingget_audio_meters()at 100ms intervals withApplication(refresh_interval=0.1)for redraws. Meters appear/disappear viaConditionalContainertied tosession.show_waveform. Styled green-on-dark-green (class:waveform-area). -
REPL word aliases for symbol commands (
parser.py,lang/constants.py): Every terse symbol command now has a readable word equivalent. New aliases:shreds(?),shred <id>(? <id>),globals(?g),audio(?a),start(>),stop(||),shutdown(X),compile <file>(: <file>),exec "code"(! "code"),shell <cmd>($ <cmd>),snippet <name>(@<name>),get <var>(<var>?),set <var> <val>(<var>::<val>),signal <ev>(<ev>!),broadcast <ev>(<ev>!!). All word aliases are tab-completable. -
REPL command cheatsheet (
docs/repl-commands.md): Standalone reference documenting every REPL command organized by category, showing both symbol and word forms. -
Wheel RECORD Validation (
scripts/check_wheel_record.py,scripts/repair_wheel.py):- New standalone script validates wheel RECORD files against actual ZIP contents -- checks for smuggled files, dangling entries, hash mismatches, and size mismatches
- Addresses wheel archive confusion attacks
- Integrated into
repair_wheel.pyas a post-repair validation step for both chugin and non-chugin wheels - Added RECORD validation steps to CI wheels workflow (per-platform and combined artifact stages)
make checknow runs RECORD validation alongsidetwine check
-
CLAP, PdPatch, and VST3 Chugins (
thirdparty/chugins/{CLAP,PdPatch,VST3}/):- Added three new chugins from my-chugins: CLAP (host CLAP plugins), PdPatch (embed Pure Data patches), and VST3 (host VST3 plugins)
- All three are enabled by default via
option(CM_CLAP/CM_PDPATCH/CM_VST3 ... ON)and bundled in release wheels - External dependencies (clap SDK 1.2.6, libpd, VST3 SDK v3.8.0) fetched automatically via CMake
FetchContent - Can be individually disabled with
-DCM_CLAP=OFF,-DCM_PDPATCH=OFF, or-DCM_VST3=OFF - macOS and Linux only -- all three depend on POSIX APIs (
dlfcn.h,dirent.h, pthreads) not available on Windows - Fixed VST3 SDK option names (
SMTG_ENABLE_VST3_PLUGIN_EXAMPLES/SMTG_ENABLE_VST3_HOSTING_EXAMPLES) to correctly disable SDK samples that requiregtk+-3.0on Linux - The numchuck package now includes:
- AbletonLink.chug
- ABSaturator.chug
- AmbPan.chug
- AudioUnit.chug
- Binaural.chug
- Bitcrusher.chug
- CLAP.chug
- ConvRev.chug
- Elliptic.chug
- ExpDelay.chug
- ExpEnv.chug
- FIR.chug
- FoldbackSaturator.chug
- GVerb.chug
- KasFilter.chug
- Ladspa.chug
- Line.chug
- MagicSine.chug
- Mesh2D.chug
- MIAP.chug
- Multicomb.chug
- NHHall.chug
- Overdrive.chug
- PanN.chug
- Patch.chug
- PdPatch.chug
- Perlin.chug
- PitchTrack.chug
- PowerADSR.chug
- Random.chug
- Range.chug
- RegEx.chug
- Sigmund.chug
- Spectacle.chug
- VST3.chug
- Wavetable.chug
- WinFuncEnv.chug
- WPDiodeLadder.chug
- WPKorg35.chug
- XML.chug
Fixed
-
Wheels workflow collect job (
.github/workflows/wheels.yml):- Reordered
collectjob steps to runcheckoutbefore artifact downloads --actions/checkout@v4cleans the working directory by default, which was wiping the downloadeddist/directory
- Reordered
-
FetchContent install leaking into wheels (
thirdparty/chugins/{CLAP,PdPatch}/CMakeLists.txt):- Added
EXCLUDE_FROM_ALLtoFetchContent_Declarefor CLAP and PdPatch to prevent their SDKinstall()rules from polluting the wheel with headers, pkgconfig, and cmake config files (reduced wheel from 186 to 100 files)
- Added
-
REPL ghost line on shred removal (
common.py): Fixed terminal rendering corruption (ghost line at bottom of screen) when removing shreds while level meters were visible. Root cause: ChucK's VM writes[chuck]: (VM) removing shred: ...directly to stdout viaCK_FPRINTF_STDOUT, bypassing prompt_toolkit's full-screen renderer. Fix:setup_output_capture()now also sets the global/staticChucK.set_stdout_callback()andChucK.set_stderr_callback()to route all VM system messages through the TUI log system. Seedocs/architecture.mdfor the two-tier callback architecture. -
REPL exception handling (
repl.py):_submit_input(TUI) andprocess_line(stdin) now catch exceptions fromexecutor.execute()andspork_code(), displaying graceful error messages instead of crashing with tracebacks. -
REPL shutdown crash (
repl.py): Fixed malloc double-free / segfault on exit. Removed staticset_stdout_callback/set_stderr_callback(which outlived the Python objects they referenced) in favor of instance-level callbacks cleaned up bychuck.shutdown(). Reordered cleanup to break all reference cycles before destroying C++ objects. -
nanobind ref leak on shutdown (
common.py): Fixed "leaked 1 instances" / "leaked 1 types" nanobind warnings on exit. Root cause:setup_output_capture()registers alog_callbackclosure (capturingself) as static class-level callbacks viaChucK.set_stdout_callback()/ChucK.set_stderr_callback(). These outlived the instance and pinned the entireChuckApplication -> ChucKobject graph, preventing C++ destructor from running. Fix:cleanup()now clears static callbacks toNonebefore breaking instance references. -
Shell command execution (
commands.py):$ <cmd>now captures stdout/stderr (routed through_log()), enforces a 30-second timeout, reports nonzero exit codes, and catchesTimeoutExpired/OSErrorinstead of running unsanitized with no output capture or error handling. -
ConvRev segfault on ARM64 macOS CI (
test_examples.py): Fixed segfault intest_chugin_convrev_exampleon macos-14 (ARM64). Root cause:_check_chugin_available()created up to 2 ChucK instances without callingshutdown(), leaving ConvRev's backgroundstd::threadactive. When the test then created a new instance, concurrent ConvRev destructor/thread cleanup races caused a segfault (ARM64's stricter memory ordering exposed this). Fix: all ChucK instances intest_examples.pynow callremove_all_shreds()+shutdown()before going out of scope. -
Windows CI test failures (
test_waveform.py): Fixed 3TestREPLMeterInfrastructuretests failing on Windows CI withNoConsoleScreenBufferError. These tests instantiateChuckREPL()which creates aprompt_toolkit.Applicationrequiring a real TTY. Fix: skip the test class when stdout is not a TTY.
Changed
-
REPL help panel (
repl.py): F1 help text now showsword / symbolforms side by side for all commands that have both. -
REPL inline transcript (
repl.py): Replaced split input/output layout with a single-buffer Python/Jupyter-style transcript. Input and output are interleaved in one scrollable area -- commands echo as[=>] ..., output is indented, errors show inline with[!]prefix. Removed separate log window (F3 toggle), error bar, and transcript TextArea. Input prompt sits at the bottom of the transcript buffer.
numchuck 0.1.10
Python bindings for the ChucK audio programming language using nanobind.
The numchuck library provides interactive control over ChucK, enabling live coding workflows, bidirectional Python/ChucK communication, and comprehensive VM introspection—all while maintaining the existing real-time and offline audio capabilities.
Changes from the last Release
Added
-
Bundled Chugins in Wheels (
scripts/cmake/fn_add_chugin.cmake,pyproject.toml,src/numchuck/api.py):- Pre-built chugins (~37
.chugfiles) are now included in distributed wheels NUMCHUCK_INSTALL_CHUGINSCMake option gates installation (ON for wheel builds, OFF for local dev)cmake.args = ["-DNUMCHUCK_INSTALL_CHUGINS=ON"]inpyproject.tomlenables bundling duringpip install/uv build- Bundled chugins directory (
<package>/chugins/) automatically added to ChucK search path inChuck.__init__ - Users no longer need to build from source to use chugins
- Pre-built chugins (~37
-
numchuck infolists bundled chugins (src/numchuck/cli/main.py):- Shows count and names of all bundled
.chugfiles from the installed package - Displays "none" for editable/dev installs where chugins are in
examples/chugins/instead
- Shows count and names of all bundled
-
Cross-Platform Wheel Repair for Chugins (
scripts/repair_wheel.py):- Wheel repair tools (delocate, auditwheel, delvewheel) skip
.chugfiles since they only scan platform-standard extensions - New repair script temporarily renames
.chugto the native extension (.dylib/.so/.dll), runs the repair tool, then renames back - Ensures chugin shared library dependencies are properly bundled if any chugin gains external (non-system) dependencies
- Uses only stdlib (
zipfile,hashlib,csv) -- no dependency on thewheelCLI package - RECORD file correctly regenerated after rename operations
- Platform-specific handling:
- macOS:
.chug->.dylib, delocate-wheel with--require-archs - Linux:
.chug->.so, auditwheel repair - Windows:
.chug->.dll, delvewheel with--analyze-existing --no-mangle
- macOS:
- Wheel repair tools (delocate, auditwheel, delvewheel) skip
-
README: Bundled chugins documentation (
README.md):- Categorized table of all 37 bundled chugins (38 on macOS with AudioUnit)
- Updated "Using Chugins" section to show automatic discovery (no manual path setup)
- Plugin Support overview links to the bundled chugins table
Changed
-
CI: Chugin tests enabled in wheel builds (
.github/workflows/wheels.yml):- Removed
and not chuginfromCIBW_TEST_COMMANDfilter - All three platforms (Linux, macOS, Windows) now use the custom repair script
- Windows builds install delvewheel via
CIBW_BEFORE_BUILD_WINDOWS
- Removed
-
Chugin test helpers updated (
tests/test_examples.py):- New
_get_chugins_dir()helper checks bundled package directory first, falls back toexamples/chugins/for dev builds - All chugin tests (
test_chugin_loading,test_chugin_bitcrusher_strict,test_chugin_gverb_strict,test_chugin_convrev_example) use the unified helper
- New
Fixed
-
TUI tests skipped on Windows (
tests/conftest.py):- Added
pytest_collection_modifyitemshook to skip@pytest.mark.tuitests on Windows - prompt_toolkit raises
NoConsoleScreenBufferErroron Windows in non-console environments - 42 TUI tests now skip gracefully on Windows instead of failing
- Added
-
WAV file rendering tests (
tests/test_wavfile.py):- Fixed
test_render_sine_to_wavrun duration:chuck.run(44100)changed tochuck.run(44100 * 4)to match 4-second ChucK code duration - Added
del chuckbefore temp directory cleanup in all tests to release file handles - Fixes
PermissionErroron Windows where files can't be deleted while open
- Fixed
-
Async awaitable race condition (
src/numchuck/api.py):get_int_awaitable,get_float_awaitable,get_string_awaitablehad a race betweenrun_in_executorcompletion andcall_soon_threadsafecallback delivery- Added
await asyncio.sleep(0)afterrun_in_executorto yield to the event loop and process pending callbacks before checkingfuture.done() - Fixes intermittent "callback not invoked" failures on slower platforms (macOS x86_64 under Rosetta)
numchuck 0.1.9
This release introduces a browser-based Web IDE for ChucK, bringing live coding to the browser with full feature parity to the terminal REPL.
Highlights
Web IDE (numchuck web)
- Browser-based ChucK IDE with code editor (codemirror) and interactive REPL
(xterm.js) - Real-time audio metering with RMS/peak level visualization
- Multi-file tabs, globals panel with interactive sliders, shred management
- Works completely offline - all assets bundled locally
- Full command parity with TUI REPL
New APIs
chuck.stream()- Iterator-based audio processing for real-time applicationsrender()/to_wav()- Offline rendering tonumpyarrays or WAV filesget_audio_meters()- Real-time RMS/peak audio levels
Developer Experience
- Automatic chugin discovery from
~/.numchuck/chugins - UGen parameter autocomplete (40+ UGens)
- File watch mode with auto-reload
- Configurable themes and key bindings
- User directory template with snippets and examples
ChucK Command Alignment
- Added
abort,=(replace),^(status) shortcuts - Full compatibility with ChucK's command syntax
Breaking Changes
- Dropped Python 3.8 and 3.9 support (now requires Python 3.10+)
- Removed chump package manager integration
See the CHANGELOG.md for the complete list of changes.