|
Download CLAUDE.md from RAM2118/pluginbridge: direct link, hf CLI and curl.
- Browser
- Download file 10.5 kB
-
https://huggingface.co/RAM2118/pluginbridge/resolve/main/CLAUDE.md
- Command line
-
hf download hf://RAM2118/pluginbridge/CLAUDE.md
-
curl -L -o CLAUDE.md https://huggingface.co/RAM2118/pluginbridge/resolve/main/CLAUDE.md
10.5 kB
| # PluginBridge β Claude Code Context | |
| ## What This Is | |
| A JUCE-based VST3/AU plugin that: | |
| 1. Hosts any third-party VST3/AU plugin with full GUI embedded in Ableton's window | |
| 2. Crash-isolates unsafe plugins by loading them in a separate Helper process (audio-only mode) | |
| 3. Exposes ALL hosted plugin parameters via a local MCP server (port 16620) | |
| 4. Audio routes through shared memory (zero added latency) | |
| 5. Any AI that speaks MCP (Claude Code, Codex CLI, Gemini CLI) can control any plugin | |
| ## Current Status (v0.6.0 β 2026-05-17) | |
| - β In-process GUI hosting (full GUI for safe plugins) | |
| - β Safety scanning system (Helper-based pre-test, results cached in safety_db.json) | |
| - β Audio-only mode for unsafe plugins (iZotope, etc.) | |
| - β Ableton-style plugin picker (manufacturer TreeView, search, safety badges) | |
| - β MCP server (port 16620, HTTP JSON-RPC 2.0) | |
| - β Live spectrum analyzer (LUFS / FFT bands / stereo width / centroid / true peak) | |
| - β Multi-instance support + channel dropdown (any PluginBridge track addressable by name) | |
| - β Verified working: Pro-Q 4, God Particle, Little MicroShift, LIMITER | |
| - β οΈ Sprint 7 in progress β MCP param ops route through Helper (not in-process) β EQ changes invisible in GUI | |
| ## Architecture: HYBRID SAFETY-SCAN | |
| ``` | |
| ββ Ableton Process βββββββββββββββββββββββββββββββββββββββββββββββ | |
| β β | |
| β PluginBridge.vst3 β | |
| β βββ PluginBridgeProcessor β | |
| β β βββ getInstalledPluginFiles() β scans VST3+AU dirs β | |
| β β βββ getPluginManufacturer() β reads Info.plist, cached β | |
| β β βββ PluginSafetyDB β safe/unsafe/unknown JSON DB β | |
| β β βββ startBackgroundScan() β pre-tests all unknown plugins β | |
| β β βββ loadPlugin() β orchestrates load flow β | |
| β β βββ McpServer β HTTP MCP port 16620 β | |
| β β β | |
| β βββ PluginBridgeEditor β | |
| β β βββ PluginPickerComponent β manufacturer TreeView + searchβ | |
| β β βββ pluginEditor β hosted plugin's own editor β | |
| β β β | |
| β βββ HelperConnection β IPC + shared memory to Helperβ | |
| β β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β Unix socket + shared memory | |
| βΌ | |
| ββ PluginBridgeHelper.app (separate process) ββββββββββββββββββββββ | |
| β Bundled in PluginBridge.vst3/Contents/Resources/ β | |
| β β | |
| β Modes: β | |
| β --load <path> Load plugin, route audio via shared memory β | |
| β --scan <path> Test-load plugin, exit 0=safe / crash=unsafe β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ``` | |
| ## Plugin Load Flow | |
| ``` | |
| User selects plugin in picker | |
| β | |
| βΌ | |
| loadPlugin() checks PluginSafetyDB | |
| β | |
| ββββββ΄βββββββββββββββββββ | |
| β β | |
| Unknown Safe/Unsafe already known | |
| β β | |
| βΌ β | |
| Wait for Helper to exit β | |
| Spawn: Helper --scan β | |
| β β | |
| Crashed? β mark Unsafe β | |
| Exit 0? β mark Safe β | |
| β β | |
| ββββββββββββββ¬βββββββββββ | |
| β | |
| βββββββββ΄βββββββββ | |
| β β | |
| Safe Unsafe | |
| β β | |
| βΌ βΌ | |
| Helper --load Helper --load | |
| (audio routing) (audio routing) | |
| β β | |
| βΌ βΌ | |
| loadInProcess() showAudioOnlyUI() | |
| createEditor() (MCP still works) | |
| embed in window | |
| ``` | |
| **Key constraint:** Only ONE Helper process at a time. Scanner must wait for live Helper to finish before spawning a scan subprocess (same shared memory name β conflict). | |
| ## File Structure | |
| ``` | |
| pluginbridge/ | |
| βββ CMakeLists.txt | |
| βββ JUCE/ (git submodule) | |
| βββ libs/ | |
| β βββ httplib.h (MIT, header-only HTTP server) | |
| β βββ json.hpp (MIT, header-only JSON) | |
| βββ Source/ | |
| β βββ Plugin/ β VST3/AU (runs inside Ableton) | |
| β β βββ PluginBridgeProcessor.h/.cpp β main logic | |
| β β βββ PluginBridgeEditor.h/.mm β editor window | |
| β β βββ PluginPickerComponent.h/.mm β plugin browser UI (new v0.5) | |
| β β βββ HelperConnection.h/.cpp β IPC + shared memory | |
| β β βββ McpServer.h/.cpp β HTTP MCP server | |
| β β βββ PluginSafetyDB.h β safe/unsafe JSON DB | |
| β β βββ Blocklist.h β persistent crash blocklist | |
| β β βββ PBLog.h β timestamped logger | |
| β βββ Helper/ β Standalone exe (separate process) | |
| β β βββ main.cpp β --load and --scan modes | |
| β β βββ HelperPluginHost.h/.mm | |
| β β βββ HelperIPC.h/.cpp | |
| β βββ Shared/ | |
| β βββ SharedAudioBuffer.h β shared memory layout | |
| β βββ IPCProtocol.h β JSON message formats | |
| β βββ Constants.h | |
| βββ CLAUDE.md β this file | |
| βββ MACHINE-CONTEXT.md β system paths, verified APIs, plugin behaviors | |
| βββ SYNC.md β what was built/fixed and when | |
| βββ FAILED-APPROACHES.md β what didn't work and why | |
| βββ ROADMAP.md | |
| ``` | |
| ## Build | |
| ```bash | |
| cd "/Volumes/T7 Shield/Users/Aditya/Downloads/AI MUSIC PRODUCTION/pluginbridge/build" | |
| cmake --build . --target PluginBridge_VST3 -- -j4 | |
| # Auto-installs to ~/Library/Audio/Plug-Ins/VST3/PluginBridge.vst3 | |
| ``` | |
| **Two targets:** | |
| - `PluginBridge_VST3` β builds + installs both plugin and Helper | |
| - `PluginBridgeHelper` β Helper standalone only | |
| **CMake 3.28 required** (system CMake 4.x incompatible with JUCE 8). | |
| ## Key Runtime Data | |
| | File | Purpose | | |
| |---|---| | |
| | `~/Library/PluginBridge/safety_db.json` | Safe/unsafe status per plugin path+mtime | | |
| | `~/Library/PluginBridge/debug.log` | Session-tagged timestamped log | | |
| | `~/Library/PluginBridge/scan.log` | Background scan output | | |
| | `~/Library/PluginBridge/blocklist.txt` | Plugins that crashed Helper during use | | |
| ## PluginPickerComponent (v0.5) | |
| `Source/Plugin/PluginPickerComponent.h/.mm` | |
| - `Entry` struct: `{ file, name, manufacturer, blocked, safety }` | |
| - Callbacks: `onPluginSelected`, `onClose`, `onClearBlocklist`, `onClearSafetyCache` | |
| - `static constexpr int kWidth = 420, kHeight = 500` | |
| - Tree: `ManufacturerTreeItem` (folder) β `PluginTreeItem` (leaf, 24px height) | |
| - Safety badges: `Safety::Safe` β `β` green; `Safety::Unsafe` β `audio only` orange; `blocked` β `β ` red | |
| - Search: `addChildComponent(searchList)` β NOT `addAndMakeVisible` (see FAILED-APPROACHES) | |
| - Custom `TreeLF` LookAndFeel overrides `drawTreeviewPlusMinusBox` for Ableton-style arrows | |
| ## JUCE 8 APIs β Verified | |
| ### Working | |
| - `formatManager.addFormat(new juce::VST3PluginFormat())` | |
| - `formatManager.addFormat(new juce::AudioUnitPluginFormat())` | |
| - `plugin->createEditor()` β message thread only | |
| - `plugin->hasEditor()` | |
| - `plugin->getParameters()` β `Array<AudioProcessorParameter*>` | |
| - `juce::MessageManager::callAsync(lambda)` β cross-thread UI updates | |
| - `addChildComponent(comp)` β adds hidden; use instead of `addAndMakeVisible` when starting invisible | |
| - `juce::TreeView` + `juce::TreeViewItem` with custom `LookAndFeel` | |
| - `juce::File::findChildFiles(findDirectories, false, "*.vst3")` | |
| ### Broken β Do NOT Use | |
| - β `addDefaultFormats()` β deleted in JUCE 8 | |
| - β `juce::Thread::setCurrentThreadPriority()` β removed, use native pthread | |
| - β `getParameter(int)` / `setParameter(int, float)` β deprecated | |
| - β `getStringWidth()` β use `getStringWidthFloat()` | |
| - β `juce::Rectangle<float>::getTransformToFit()` β does not exist | |
| - β `juce::Array<CustomStruct>` initializer list β use `std::vector<CustomStruct>` | |
| ## macOS Gotchas | |
| - β `MSG_NOSIGNAL` β Linux only β `signal(SIGPIPE, SIG_IGN)` + `SO_NOSIGPIPE` | |
| - β Two processes with same `shm_open` name β both crash β scanner must wait for Helper | |
| - β `addAndMakeVisible(comp)` after `comp.setVisible(false)` β `addAndMakeVisible` forces visible, invisible comp sits on top intercepting all mouse events β use `addChildComponent(comp)` instead | |
| - β `CAContext` + `CALayerHost` for cross-process GUI β doesn't work in Ableton (see FAILED-APPROACHES #10) | |
| - β `posix_spawn` β safe for spawning from plugin process | |
| - β `shm_open` / `mmap` β reliable cross-process shared memory | |
| ## MCP Protocol | |
| - Endpoint: `POST http://127.0.0.1:16620/mcp` | |
| - Health: `GET http://127.0.0.1:16620/health` | |
| - Wire format: JSON-RPC 2.0 | |
| - Tools: `list_plugins`, `search_param`, `get_params`, `set_params`, `get_analysis` | |
| ## What NOT To Do | |
| - Don't load plugins in-process without safety scan β crash-prone plugins (iZotope, some Waves) call `abort()` and kill Ableton | |
| - Don't use `PluginDirectoryScanner` β triggers plugin code on scan β crash | |
| - Don't spawn Helper --scan while live Helper is running β shared memory conflict β false UNSAFE results | |
| - Don't use `addAndMakeVisible` on a component that should start hidden β use `addChildComponent` | |
| - Don't try CAContext/CALayerHost for cross-process GUI β see FAILED-APPROACHES #10 | |