RAM2118 commited on
Commit
47e9eca
·
verified ·
1 Parent(s): 97989ed

Update CLAUDE.md — reflect Sprint 2 complete, fix API notes, update status

Browse files
Files changed (1) hide show
  1. CLAUDE.md +55 -60
CLAUDE.md CHANGED
@@ -7,14 +7,22 @@ A JUCE-based VST3/AU plugin that:
7
  3. Provides real-time audio analysis (LUFS, FFT bands, stereo width)
8
  4. Any AI that speaks MCP (Claude Code, Codex CLI, Gemini CLI) can control any plugin
9
 
 
 
 
 
 
 
10
  ## Project Decisions (Confirmed)
11
  - **Platform:** macOS only (for now)
12
- - **License:** GPL (JUCE GPL mode — no commercial license needed)
13
  - **VST3 install path:** `~/Library/Audio/Plug-Ins/VST3/`
14
  - **AU install path:** `~/Library/Audio/Plug-Ins/Components/`
15
- - **Test plugins:** FabFilter Pro-Q 4 (EQ, many params), LA-2A compressor (fewer params)
16
- - **Xcode:** 14+ required (user should verify with `xcode-select --version`)
 
17
  - **DAW:** Ableton Live (primary), Logic Pro (secondary AU test)
 
18
 
19
  ## Architecture (Single Plugin Host, Not a Graph)
20
  ```
@@ -23,39 +31,49 @@ PluginBridgeProcessor (AudioProcessor — the outer VST3/AU shell)
23
  ├── McpServer (httplib) → JSON-RPC 2.0 on http://127.0.0.1:16620/mcp
24
  ├── AudioAnalyser → LUFS + 7-band FFT + stereo width in processBlock
25
  └── processBlock():
26
- buffer → analyser.process(buffer)
27
- → hostedPlugin->processBlock(buffer, midi)
28
- → output
29
  ```
30
 
31
  ## Build System
32
  - **JUCE 8** via CMake (git submodule at `/JUCE`)
33
  - **cpp-httplib** — single header `libs/httplib.h` (MIT)
34
  - **nlohmann/json** — single header `libs/json.hpp` (MIT)
35
- - **LUFSMeter** — 4 files in `Source/LufsMeter/` (MIT, from klangfreund/LUFSMeter)
36
  - **Target formats:** VST3 + AU (macOS only)
37
- - **Build:** `mkdir build && cd build && cmake .. && cmake --build .`
38
- - **Install:** `COPY_PLUGIN_AFTER_BUILD=TRUE` in CMake copies to system plugin dirs
39
 
40
  ## MCP Protocol
41
  - Transport: Streamable HTTP (NOT stdio — we're inside a DAW process)
42
  - Endpoint: `POST http://127.0.0.1:16620/mcp`
 
43
  - Wire format: JSON-RPC 2.0
44
  - Handshake: `initialize` → `notifications/initialized` → then tools/list, tools/call
45
- - 5 tools only: `list_plugins`, `search_param`, `get_params`, `set_params`, `get_analysis`
46
- - Session: Server returns `Mcp-Session-Id` header on init, client echoes it back
47
- - Security: bind 127.0.0.1 only, validate Origin header
48
 
49
- ## Key JUCE APIs (Correct, Verified Against JUCE 8 Source)
50
- - `addDefaultFormatsToManager(formatManager)` — NOT deprecated `addDefaultFormats()`
51
- - `formatManager.createPluginInstanceAsync(desc, sr, bs, callback)` — ALWAYS async (AU requires it)
52
  - `instance->enableAllBuses()` — MUST call before using
53
  - `plugin->getParameters()` → `Array<AudioProcessorParameter*>`
54
- - Cast to `AudioPluginInstance::HostedParameter*` for `getParameterID()` (stable string ID)
55
- - `param->beginChangeGesture()` / `setValueNotifyingHost(val)` / `endChangeGesture()` — for DAW automation
56
- - `juce::dsp::FFT` for spectral analysis (NOT KissFFT, NOT Gist — those are GPL)
57
- - `juce::dsp::Oversampling<float>` for True Peak measurement (4× oversample)
58
- - `juce::dsp::WindowingFunction<float>::hann` for FFT windowing
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  ## Design Laws (Non-Negotiable)
61
  - Never return all parameters — search first, fetch by ID
@@ -67,58 +85,35 @@ PluginBridgeProcessor (AudioProcessor — the outer VST3/AU shell)
67
 
68
  ## Thread Safety Rules
69
  - HTTP handlers run on httplib's thread pool — NOT audio thread
70
- - Use `std::atomic<float>` for analysis values queried by HTTP
71
- - Use `CriticalSection` / `ScopedLock` for plugin hot-swap
72
- - Never call `getValue()` directly from HTTP thread — read from atomic cache
73
- - Cap httplib thread pool to 2-4 threads (reduce OS pressure in plugin host)
74
  - `httplib::Server` lifecycle: constructor starts thread, destructor calls stop()+join()
75
 
76
- ## Sprint Order
77
- 1. **Sprint 1**: Empty plugin shell + httplib server responding to curl ← START HERE
78
- 2. **Sprint 2**: Host Pro-Q 4, route audio, enumerate params
79
- 3. **Sprint 3**: MCP JSON-RPC dispatch, all 5 tools working from Claude Code
80
- 4. **Sprint 4**: Audio analysis (LUFS, FFT bands, stereo, True Peak)
81
-
82
  ## What NOT To Do
83
  - Don't use `AudioProcessorGraph` — we host ONE plugin, not a graph
84
- - Don't use `AudioPluginHost`'s settings file — use runtime file picker
85
- - Don't fork `getdunne/juce-plugin-wrapper` — dead, GPL, JUCE 6
86
- - Don't use Gist or Sound-Analyser code — GPL license conflict (we're already GPL but want MIT deps)
87
  - Don't use stdio MCP transport — plugin is inside DAW, not a subprocess
88
- - Don't use `getParameter(int)` / `setParameter(int, float)` — deprecated, asserts in debug
89
  - Don't target Windows yet — macOS only for now
90
- - Don't scan system plugins on load — use file picker for explicit selection
91
-
92
- ## First Steps for Claude Code
93
- 1. Run `xcode-select --version` to verify Xcode 14+
94
- 2. Run `cmake --version` to verify CMake 3.22+
95
- 3. Clone JUCE 8 as submodule: `git submodule add https://github.com/juce-framework/JUCE.git`
96
- 4. Download `httplib.h` from yhirose/cpp-httplib into `libs/`
97
- 5. Download `json.hpp` from nlohmann/json into `libs/`
98
- 6. Create CMakeLists.txt (see ROADMAP.md for skeleton)
99
- 7. Create Source/ files (empty stubs first)
100
- 8. Build: `mkdir build && cd build && cmake .. -G Xcode && cmake --build . --config Release`
101
- 9. Verify plugin appears in `~/Library/Audio/Plug-Ins/VST3/`
102
- 10. Load in Ableton → verify audio passthrough
103
- 11. Verify `curl -X POST http://localhost:16620/mcp -d '{}'` gets a response
104
 
105
  ## Repo Structure
106
  ```
107
  pluginbridge/
108
- ├── CLAUDE.md ← this file (Claude Code reads automatically)
109
- ├── ROADMAP.md ← full technical roadmap with code samples
110
- ├── CMakeLists.txt
 
 
111
  ├── JUCE/ ← git submodule
112
  ├── libs/
113
- │ ├── httplib.h ← cpp-httplib (yhirose/cpp-httplib)
 
114
  │ └── json.hpp ← nlohmann/json
115
  └── Source/
116
- ├── PluginBridgeProcessor.h/.cpp
117
- ├── PluginBridgeEditor.h/.cpp
118
- ├── HostedPluginManager.h/.cpp
119
- ├── McpServer.h/.cpp
120
- ├── AudioAnalyser.h/.cpp
121
- └── LufsMeter/
122
- ├── Ebu128LoudnessMeter.h/.cpp
123
- └── SecondOrderIIRFilter.h/.cpp
124
  ```
 
7
  3. Provides real-time audio analysis (LUFS, FFT bands, stereo width)
8
  4. Any AI that speaks MCP (Claude Code, Codex CLI, Gemini CLI) can control any plugin
9
 
10
+ ## Current Status
11
+ - **Sprint 1:** ✅ Done — plugin shell + MCP server responding
12
+ - **Sprint 2:** ✅ Done — hosts Pro-Q 4 (737 params), routes audio, MCP tools wired
13
+ - **Sprint 3:** Next — full MCP client integration test from Claude Code
14
+ - **Sprint 4:** Pending — real-time audio analysis
15
+
16
  ## Project Decisions (Confirmed)
17
  - **Platform:** macOS only (for now)
18
+ - **License:** GPL (JUCE GPL mode — no commercial license needed, doesn't hamper project)
19
  - **VST3 install path:** `~/Library/Audio/Plug-Ins/VST3/`
20
  - **AU install path:** `~/Library/Audio/Plug-Ins/Components/`
21
+ - **Test plugins:** FabFilter Pro-Q 4 (EQ, 737 params), LA-2A compressor (fewer params)
22
+ - **Xcode:** CLI tools 2410+ (no full Xcode.app needed)
23
+ - **CMake:** 3.28 via pip (system CMake 4.x incompatible with JUCE 8)
24
  - **DAW:** Ableton Live (primary), Logic Pro (secondary AU test)
25
+ - **Build generator:** Unix Makefiles or Ninja (NOT Xcode generator — no Xcode.app)
26
 
27
  ## Architecture (Single Plugin Host, Not a Graph)
28
  ```
 
31
  ├── McpServer (httplib) → JSON-RPC 2.0 on http://127.0.0.1:16620/mcp
32
  ├── AudioAnalyser → LUFS + 7-band FFT + stereo width in processBlock
33
  └── processBlock():
34
+ buffer → hostManager.processBlock(buffer, midi)
35
+ → output (audio routed through hosted plugin)
 
36
  ```
37
 
38
  ## Build System
39
  - **JUCE 8** via CMake (git submodule at `/JUCE`)
40
  - **cpp-httplib** — single header `libs/httplib.h` (MIT)
41
  - **nlohmann/json** — single header `libs/json.hpp` (MIT)
42
+ - **LUFSMeter** — 4 files in `Source/LufsMeter/` (MIT, from klangfreund/LUFSMeter) — Sprint 4
43
  - **Target formats:** VST3 + AU (macOS only)
44
+ - **Build:** `cd build && cmake .. -DCMAKE_C_COMPILER=/usr/bin/cc -DCMAKE_CXX_COMPILER=/usr/bin/c++ && cmake --build . --config Release`
45
+ - **Install:** `COPY_PLUGIN_AFTER_BUILD=TRUE` copies to `~/Library/Audio/Plug-Ins/VST3/`
46
 
47
  ## MCP Protocol
48
  - Transport: Streamable HTTP (NOT stdio — we're inside a DAW process)
49
  - Endpoint: `POST http://127.0.0.1:16620/mcp`
50
+ - Health check: `GET http://127.0.0.1:16620/health`
51
  - Wire format: JSON-RPC 2.0
52
  - Handshake: `initialize` → `notifications/initialized` → then tools/list, tools/call
53
+ - 5 tools: `list_plugins`, `search_param`, `get_params`, `set_params`, `get_analysis`
 
 
54
 
55
+ ## Key JUCE 8 APIs (Verified — these WORK)
56
+ - `formatManager.addFormat(new juce::VST3PluginFormat())` — explicit registration
57
+ - `formatManager.addFormat(new juce::AudioUnitPluginFormat())` — explicit registration
58
  - `instance->enableAllBuses()` — MUST call before using
59
  - `plugin->getParameters()` → `Array<AudioProcessorParameter*>`
60
+ - Cast to `juce::AudioPluginInstance::HostedParameter*` for `getParameterID()`
61
+ - `param->beginChangeGesture()` / `setValueNotifyingHost(val)` / `endChangeGesture()`
62
+ - `juce::dsp::FFT` for spectral analysis
63
+ - `juce::PluginDirectoryScanner` for system plugin scan
64
+ - `juce::KnownPluginList` for storing scan results
65
+
66
+ ## Key JUCE 8 APIs (BROKEN — do NOT use)
67
+ - ❌ `addDefaultFormats()` — deleted in JUCE 8, use explicit addFormat() calls
68
+ - ❌ `addDefaultFormatsToManager()` — also deleted
69
+ - ❌ `getParameter(int)` / `setParameter(int, float)` — deprecated, asserts
70
+
71
+ ## Plugin Discovery UX
72
+ - Click "Select Plugin..." button → first click triggers background scan
73
+ - Button shows "Scanning..." while scanning (background thread, non-blocking)
74
+ - After scan: popup menu grouped by manufacturer → plugin name
75
+ - Subsequent clicks: instant menu (cached scan results)
76
+ - NO file browser — clean DAW-style UX
77
 
78
  ## Design Laws (Non-Negotiable)
79
  - Never return all parameters — search first, fetch by ID
 
85
 
86
  ## Thread Safety Rules
87
  - HTTP handlers run on httplib's thread pool — NOT audio thread
88
+ - Plugin scan runs in background thread — NOT message thread (crashes DAW otherwise)
89
+ - Use `CriticalSection` / `ScopedLock` for plugin hot-swap in processBlock
90
+ - Cap httplib thread pool to 2 threads
 
91
  - `httplib::Server` lifecycle: constructor starts thread, destructor calls stop()+join()
92
 
 
 
 
 
 
 
93
  ## What NOT To Do
94
  - Don't use `AudioProcessorGraph` — we host ONE plugin, not a graph
95
+ - Don't scan plugins on editor open — scan only on button click, in background thread
96
+ - Don't use `addDefaultFormats()` — deleted in JUCE 8
 
97
  - Don't use stdio MCP transport — plugin is inside DAW, not a subprocess
 
98
  - Don't target Windows yet — macOS only for now
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
  ## Repo Structure
101
  ```
102
  pluginbridge/
103
+ ├── CLAUDE.md ← this file
104
+ ├── ROADMAP.md ← full technical roadmap
105
+ ├── SYNC.md ← coordination between HF Claude and Claude Code
106
+ ├── CMakeLists.txt ← JUCE 8 CMake (LANGUAGES C CXX)
107
+ ├── .gitignore
108
  ├── JUCE/ ← git submodule
109
  ├── libs/
110
+ │ ├── README.md ← download instructions
111
+ │ ├── httplib.h ← cpp-httplib
112
  │ └── json.hpp ← nlohmann/json
113
  └── Source/
114
+ ├── PluginBridgeProcessor.h/.cpp ← main AudioProcessor, owns HostedPluginManager + McpServer
115
+ ├── PluginBridgeEditor.h/.cpp ← GUI: status + plugin selector popup menu
116
+ ├── HostedPluginManager.h/.cpp ← loads VST3/AU, enumerates params, routes audio
117
+ ├── McpServer.h/.cpp ← HTTP server, JSON-RPC dispatch, 5 tools
118
+ └── AudioAnalyser.h/.cpp ← stub (Sprint 4)
 
 
 
119
  ```