@mthines/reaper-mcp 0.19.0 → 0.70.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +19 -570
  2. package/bridge-ui/mcp_bridge.html +129 -0
  3. package/bridge-ui/mcp_bridge.webmanifest +16 -0
  4. package/bridge-ui/mcp_bridge_icon_192.png +0 -0
  5. package/bridge-ui/mcp_bridge_icon_512.png +0 -0
  6. package/bridge-ui/mcp_bridge_sw.js +35 -0
  7. package/claude/agents/plugin-researcher.md +188 -0
  8. package/claude/knowledge/reference/aesthetics-scoring.md +48 -0
  9. package/{knowledge → claude/knowledge}/reference/common-mistakes.md +1 -1
  10. package/claude/knowledge/reference/lorekit-setup.md +36 -0
  11. package/claude/knowledge/reference/memory-protocol.md +377 -0
  12. package/{knowledge → claude/knowledge}/reference/metering.md +5 -5
  13. package/claude/knowledge/reference/perceived-loudness.md +182 -0
  14. package/{knowledge → claude/knowledge}/workflows/editing.md +4 -0
  15. package/{knowledge → claude/knowledge}/workflows/gain-staging.md +21 -23
  16. package/{knowledge → claude/knowledge}/workflows/learn-plugin.md +15 -48
  17. package/{knowledge → claude/knowledge}/workflows/master-bus.md +13 -1
  18. package/claude/knowledge/workflows/section-levels.md +138 -0
  19. package/{knowledge → claude/knowledge}/workflows/session-prep.md +4 -0
  20. package/claude/knowledge/workflows/transient-lighting.md +52 -0
  21. package/claude/skills/critique/SKILL.md +131 -0
  22. package/claude/skills/editing/SKILL.md +281 -0
  23. package/claude/skills/learn-plugin/SKILL.md +210 -0
  24. package/claude/skills/mastering/SKILL.md +151 -0
  25. package/claude/skills/mix-memory/SKILL.md +140 -0
  26. package/claude/skills/mixer/SKILL.md +253 -0
  27. package/claude/skills/new-extension/SKILL.md +324 -0
  28. package/main.js +7843 -1940
  29. package/package.json +17 -15
  30. package/reaper/CLAUDE.md +22 -4
  31. package/reaper/mcp_actions_lib.lua +375 -0
  32. package/reaper/mcp_analyzer.jsfx +27 -12
  33. package/reaper/mcp_arrange_lib.lua +949 -0
  34. package/reaper/mcp_bridge.lua +2321 -758
  35. package/reaper/mcp_edit_views_lib.lua +1378 -0
  36. package/reaper/mcp_envelopes_lib.lua +748 -0
  37. package/reaper/mcp_extensions_lib.lua +55 -0
  38. package/reaper/mcp_fxstate_lib.lua +144 -0
  39. package/reaper/mcp_gain_trace.jsfx +126 -0
  40. package/reaper/mcp_items_lib.lua +877 -0
  41. package/reaper/mcp_lufs_meter.jsfx +16 -13
  42. package/reaper/mcp_midi_lib.lua +555 -0
  43. package/reaper/mcp_mixing_lib.lua +1021 -0
  44. package/reaper/mcp_plan_lib.lua +801 -0
  45. package/reaper/mcp_prefs_lib.lua +127 -0
  46. package/reaper/mcp_project_lib.lua +1088 -0
  47. package/reaper/mcp_recording_lib.lua +595 -0
  48. package/reaper/mcp_render_lib.lua +492 -0
  49. package/reaper/mcp_snapshot_lib.lua +547 -120
  50. package/reaper/mcp_snapshot_next.lua +10 -4
  51. package/reaper/mcp_snapshot_prev.lua +11 -4
  52. package/reaper/mcp_snapshot_quick_save.lua +7 -32
  53. package/reaper/mcp_snapshots_ui_lib.lua +258 -0
  54. package/reaper/mcp_tracks_lib.lua +409 -0
  55. package/sidecar/analysis.py +661 -0
  56. package/sidecar/chords.py +96 -0
  57. package/sidecar/mixcheck.py +295 -0
  58. package/sidecar/requirements-chords.txt +6 -0
  59. package/sidecar/requirements-separation.txt +3 -0
  60. package/sidecar/requirements.txt +17 -0
  61. package/sidecar/separation.py +142 -0
  62. package/sidecar/server.py +622 -0
  63. package/sidecar/tests/test_analysis.py +249 -0
  64. package/sidecar/tests/test_chords.py +117 -0
  65. package/sidecar/tests/test_mixcheck.py +163 -0
  66. package/sidecar/tests/test_separation.py +73 -0
  67. package/sidecar/tests/test_server.py +464 -0
  68. package/sidecar/tests/test_verify.py +243 -0
  69. package/sidecar/tests/test_voice_render.py +268 -0
  70. package/sidecar/tests/test_voice_sketch.py +140 -0
  71. package/sidecar/verify.py +224 -0
  72. package/sidecar/voice_render.py +295 -0
  73. package/sidecar/voice_sketch.py +280 -0
  74. package/claude-agents/critique.md +0 -147
  75. package/claude-agents/editor.md +0 -184
  76. package/claude-agents/levels.md +0 -107
  77. package/claude-agents/mastering.md +0 -129
  78. package/claude-agents/mixer.md +0 -248
  79. package/claude-agents/preflight.md +0 -149
  80. package/claude-agents/producer.md +0 -159
  81. package/claude-agents/setup.md +0 -150
  82. package/claude-agents/stems.md +0 -135
  83. package/claude-rules/architecture.md +0 -39
  84. package/claude-rules/development.md +0 -54
  85. package/claude-rules/lua-bridge.md +0 -50
  86. package/claude-rules/testing.md +0 -42
  87. package/claude-skills/learn-plugin.md +0 -123
  88. package/knowledge/CLAUDE.md +0 -71
  89. package/knowledge/plugins/_template.md +0 -82
  90. package/knowledge/plugins/fabfilter/pro-c-2.md +0 -117
  91. package/knowledge/plugins/fabfilter/pro-l-2.md +0 -95
  92. package/knowledge/plugins/fabfilter/pro-q-3.md +0 -112
  93. package/knowledge/plugins/neural-dsp/helix-native.md +0 -104
  94. package/knowledge/plugins/stock-reaper/js-1175-compressor.md +0 -94
  95. package/knowledge/plugins/stock-reaper/rea-comp.md +0 -100
  96. package/knowledge/plugins/stock-reaper/rea-delay.md +0 -95
  97. package/knowledge/plugins/stock-reaper/rea-eq.md +0 -103
  98. package/knowledge/plugins/stock-reaper/rea-gate.md +0 -99
  99. package/knowledge/plugins/stock-reaper/rea-limit.md +0 -75
  100. package/knowledge/plugins/stock-reaper/rea-verb.md +0 -76
  101. package/knowledge/reference/perceived-loudness.md +0 -122
  102. package/reaper/mcp_snapshot_manager.lua +0 -1001
  103. /package/{knowledge → claude/knowledge}/genres/_template.md +0 -0
  104. /package/{knowledge → claude/knowledge}/genres/electronic.md +0 -0
  105. /package/{knowledge → claude/knowledge}/genres/hip-hop.md +0 -0
  106. /package/{knowledge → claude/knowledge}/genres/metal.md +0 -0
  107. /package/{knowledge → claude/knowledge}/genres/orchestral.md +0 -0
  108. /package/{knowledge → claude/knowledge}/genres/pop.md +0 -0
  109. /package/{knowledge → claude/knowledge}/genres/rock.md +0 -0
  110. /package/{knowledge → claude/knowledge}/reference/compression.md +0 -0
  111. /package/{knowledge → claude/knowledge}/reference/frequencies.md +0 -0
  112. /package/{knowledge → claude/knowledge}/workflows/delivery.md +0 -0
  113. /package/{knowledge → claude/knowledge}/workflows/drum-bus.md +0 -0
  114. /package/{knowledge → claude/knowledge}/workflows/low-end.md +0 -0
  115. /package/{knowledge → claude/knowledge}/workflows/stem-prep.md +0 -0
  116. /package/{knowledge → claude/knowledge}/workflows/vocal-chain.md +0 -0
@@ -0,0 +1,140 @@
1
+ ---
2
+ name: mix-memory
3
+ description: Recall and maintain the mixing skills' memory in LoreKit (scope project::reaper-mcp) — plugin knowledge records and self-healing process lessons, as a read-only built-in layer plus the user's own layer on top. Modes — recall (load what's relevant before work), consolidate (merge duplicate user lessons, fold proven plugin notes into recommended settings), promote (turn a recurring lesson into a hard rule), publish (maintainer only — move a user record into the built-in layer), status (what's stored, per layer). Triggers on "what have you learned", "recall mixing memory", "consolidate memory", "promote that lesson", "publish to built-in", "/mix-memory".
4
+ disable-model-invocation: false
5
+ argument-hint: '[recall|consolidate|promote|publish|status] [plugin-slug|lesson-slug]'
6
+ ---
7
+
8
+ # /mix-memory
9
+
10
+ Maintain and recall the two kinds of memory the mixing skills keep in
11
+ **LoreKit** (scope `project::reaper-mcp`, via the `memory.*` MCP tools):
12
+
13
+ - **Process lessons** — tag `loop::mixing-lessons`
14
+ - **Plugin knowledge** — tag `plugin-knowledge`
15
+
16
+ Each comes in two layers: the built-in one, read through the `reaper` tools
17
+ `list_builtin_knowledge` / `get_builtin_knowledge` (public read-only token, no
18
+ LoreKit account needed), and the user's own, through `memory.*`:
19
+
20
+ | Layer | Keys | Tag | Writable here |
21
+ |-------|------|-----|---------------|
22
+ | Built-in (`reaper-mcp` org, curated) | `plugins::<vendor>/<plugin>`, `mixing-lessons::<slug>` | `layer::built-in` | only via `publish` |
23
+ | User (personal) | `user::plugins::<vendor>/<plugin>`, `user::mixing-lessons::<slug>` | `layer::user` | yes |
24
+
25
+ **Never write or `memory.delete` a built-in key outside `publish`** — a delete
26
+ without `org` archives the org row too.
27
+
28
+ The full contract — buckets, body shapes,
29
+ entrenchment guards — is `knowledge/reference/memory-protocol.md`; read it before
30
+ any write. If the `memory.*` tools are not connected, read `~/.claude/knowledge/reference/lorekit-setup.md` (in a clone: `knowledge/reference/lorekit-setup.md`), walk the user through connecting LoreKit, and carry on once it is (stop only if they decline).
31
+
32
+ ## Mode detection
33
+
34
+ Parse the first argument:
35
+
36
+ | Mode | Default | Trigger phrases |
37
+ |------|---------|-----------------|
38
+ | `recall` | **yes** | "what have you learned", "recall", "what do you know about {plugin}" |
39
+ | `consolidate` | | "consolidate memory", "compress memory", "tidy memory" |
40
+ | `promote` | | "promote that lesson", "make it a rule" |
41
+ | `publish` | | "publish to built-in", "make it a default", "share this plugin record" |
42
+ | `status` | | "memory status", "what's stored", "list memory" |
43
+
44
+ State the detected mode in one line before acting.
45
+
46
+ ---
47
+
48
+ ## recall
49
+
50
+ 1. Lessons: `memory.list { scope: "project::reaper-mcp", tags: ["loop::mixing-lessons"], order: "rank", limit: 5 }`
51
+ — plus a `memory.search` on the current task's keywords. Surface those whose
52
+ **Applies when** matches.
53
+ 2. For a named plugin: `get_builtin_knowledge { key: "plugins::<vendor>/<plugin>" }`
54
+ and `memory.read` of `user::plugins::<vendor>/<plugin>` (find the slug via the `fx::` tags if you
55
+ only have an FX name) and report the combined record, marking what comes from
56
+ the user's layer.
57
+ 3. No argument: summarise — lesson count per layer, which plugins are known (built-in,
58
+ user, or both; which have learned notes), anything
59
+ promotion-eligible (`seen_count >= 3` or tag `status::structural`, not yet
60
+ `status::promoted`).
61
+
62
+ This is what the mixer/mastering/critique skills do automatically at the start of
63
+ work — use this mode to inspect memory manually.
64
+
65
+ ---
66
+
67
+ ## consolidate
68
+
69
+ Show a preview of every change and get confirmation before writing.
70
+
71
+ Only `user::` records are touched — the built-in layer is read-only.
72
+
73
+ - **Lessons** — `memory.list` the bucket (`view: "summary"`), find near-duplicate
74
+ `user::` lessons, merge each pair into the older key (rewrite its body with the
75
+ sharper "Do this instead"), then `memory.delete` the duplicate. A `user::` lesson
76
+ that just repeats a built-in one adds nothing beyond its recurrence count — keep
77
+ it. Expiry is automatic — never archive by hand.
78
+ - **Plugin overlays** — when `## Learned notes` sprawl, or kept settings have
79
+ proven themselves across contexts: fold them into the same `user::` record's
80
+ `## Recommended settings` tables and trim them from the notes (read-merge-write,
81
+ full tag list, no `ttl_days`). Param maps and gotchas stay in the notes.
82
+
83
+ ---
84
+
85
+ ## promote
86
+
87
+ The self-heal step. For a lesson at `seen_count >= 3` or tagged `status::structural`:
88
+ 1. Show the lesson and the one-line hard rule it would become.
89
+ 2. On approval, append that rule to the **`## Hard Rules` (or `## Rules`) of the
90
+ skill that owns the behavior** — `mixer` for mix moves, `mastering` for
91
+ master-bus moves, `critique` for analysis/flagging lessons
92
+ (`.claude/skills/{skill}/SKILL.md`).
93
+ 3. Re-write the lesson with the same key, value and `ttl_days`, adding the tag
94
+ `status::promoted` (audit trail; it stops re-suggesting). For a built-in lesson,
95
+ write that tag on a `user::` copy instead — or, as the maintainer, `publish` it.
96
+
97
+ Respect the entrenchment guards in `memory-protocol.md` — never promote a lesson
98
+ that would relax an existing hard rule.
99
+
100
+ ---
101
+
102
+ ## publish
103
+
104
+ Maintainer only: turn a proven `user::` record into a built-in default every user
105
+ of the `reaper-mcp` org sees.
106
+
107
+ 1. `org.list` — continue only if the `reaper-mcp` org is listed with a writing
108
+ role (member, admin or owner). A viewer, or no membership: say so and stop
109
+ (the write would land in the personal store as a second copy).
110
+ 2. Read the `user::` record and, if present, the built-in record of the same slug.
111
+ Merge them (plugin: the overlay's sections over the built-in ones, learned
112
+ notes folded together; lesson: the sharper body). Strip anything personal per
113
+ the privacy guard. Show the merged record and get approval.
114
+ 3. `memory.write` with `org: "reaper-mcp"`, the key **without** `user::`, the
115
+ tags with `layer::built-in` in place of `layer::user`, and **no** `ttl_days`
116
+ (curated records are permanent).
117
+ 4. `memory.read` the built-in key to confirm, then `memory.delete` the `user::`
118
+ key (never the built-in key).
119
+ 5. **Plugin records only: update the built-in plugin list** (`docs/PLUGINS.md` in
120
+ the reaper-mcp clone). Find the clone: the current directory when it has
121
+ `scripts/plugin-list.mjs`, else the directory this skill is symlinked from
122
+ (`readlink ~/.claude/skills/mix-memory` → `<clone>/.claude/skills/mix-memory`).
123
+ Run `node <clone>/scripts/plugin-list.mjs`; it rebuilds the table from the
124
+ built-in layer, so it also picks up anything published earlier. Show the
125
+ changed rows and tell the maintainer to commit `docs/PLUGINS.md` (the
126
+ bridge's one-click Update refuses while the clone has local changes). No
127
+ clone found, or the script fails: say so; the daily **Plugin list** workflow
128
+ updates the list on `main` anyway.
129
+
130
+ ---
131
+
132
+ ## status
133
+
134
+ Print a compact summary from `list_builtin_knowledge { limit: 100 }` (built-in) and
135
+ `memory.list { scope: "project::reaper-mcp", tags: ["loop::mixing-lessons", "plugin-knowledge"], view: "summary", limit: 100 }` (yours):
136
+ lesson count per layer (`layer::` tag) and how many are promotion-eligible,
137
+ nearest lesson expiries, and known plugins grouped by `category::` (with
138
+ preference, marked built-in / user / both). If the built-in tools error, say the
139
+ built-in layer is unreachable (offline) and the user's own layer works alone. Suggest `consolidate`
140
+ when duplicate lessons show up or a plugin record's notes sprawl.
@@ -0,0 +1,253 @@
1
+ ---
2
+ name: mixer
3
+ description: >
4
+ Mixes a live REAPER session — gain staging, FX chains, EQ, compression, and
5
+ problem-solving — executing changes in real time via the reaper MCP tools and
6
+ verifying with meters. Reads and writes personal plugin + process memory so it
7
+ improves each session. Use when the user asks to mix, balance, gain stage, build
8
+ a vocal or drum chain, fix the low end, or make something cut through. Triggers
9
+ on "mix this", "gain stage", "fix the low end", "build a vocal chain", "/mixer".
10
+ argument-hint: '[what to mix or fix]'
11
+ license: MIT
12
+ metadata:
13
+ author: mthines
14
+ version: '1.0.0'
15
+ workflow_type: applied
16
+ tags:
17
+ - mixing
18
+ - reaper
19
+ - gain-staging
20
+ - fx
21
+ - eq
22
+ - compression
23
+ - audio
24
+ ---
25
+
26
+ # Mixer
27
+
28
+ Act as a professional mix engineer operating a **live** REAPER session through
29
+ the `reaper` MCP tools — analyze, reason in audio-engineering terms, **execute
30
+ changes in real time**, then verify with meters. You run in the current session
31
+ (which already holds the REAPER connection); call the tools directly.
32
+
33
+ The `reaper` server exposes the full tool set (tracks, FX, transport, metering,
34
+ MIDI, media, envelopes, snapshots) — their schemas are already available, so call
35
+ them rather than expecting a catalog here. When unsure of a plugin's exact name,
36
+ use `search_fx`; FX parameters are normalized 0.0–1.0, so read `get_fx_parameters`
37
+ before setting one.
38
+
39
+ ## Core principles
40
+
41
+ 1. **Snapshot before changes** — `snapshot_save`, so the user can A/B and revert.
42
+ 2. **Recall memory, then measure, then act** (see Memory + Workflow below).
43
+ 3. **Explain the reasoning** in audio terms, then execute.
44
+ 4. **Use the best available plugin** — `list_available_fx`, then prefer the
45
+ highest `preference::` among LoreKit plugin records that match; fall back to stock.
46
+ 5. **Iterate** — change, verify with meters, adjust.
47
+ 6. **Decide on perceived loudness, never raw values** — the ear is far more
48
+ sensitive at 2–5 kHz than at 100 Hz, and peak/RMS dBFS or raw band `db` ignore
49
+ that. Balance in **LU** (short-term LUFS of each element against the mix bus,
50
+ same section, post-fader), tone and masking in **`kDb`** (K-weighted bands).
51
+ Load `reference/perceived-loudness.md` for any balance or EQ decision: it
52
+ has the rules, the per-band K gains and the stem reference points.
53
+
54
+ ## Memory — get better every session
55
+
56
+ Plugin knowledge and process lessons live in **LoreKit**, scope
57
+ `project::reaper-mcp`, via the `memory.*` tools, in two layers: the read-only
58
+ **built-in** layer (`plugins::…`, `mixing-lessons::…`, tag `layer::built-in`) and
59
+ the user's own layer on top (`user::plugins::…`, `user::mixing-lessons::…`, tag
60
+ `layer::user`). Read the built-in layer with the `reaper` tools
61
+ `list_builtin_knowledge` / `get_builtin_knowledge` (no LoreKit account needed) and
62
+ the user layer with `memory.*`; the user's record wins. **Every write goes to a
63
+ `user::` key — never write or delete a built-in key.** Governed by
64
+ `reference/memory-protocol.md` (read it before any write — it has the exact calls,
65
+ record shapes, layer merge and plugin lookup):
66
+
67
+ - **Start of task:** read the `loop::mixing-lessons` bucket (capped at 5, plus one
68
+ search on the task's keywords) and treat matching lessons as soft constraints.
69
+ For each plugin you'll touch, read both `get_builtin_knowledge
70
+ { key: "plugins::{vendor}/{plugin}" }` and `memory.read` of
71
+ `user::plugins::{vendor}/{plugin}` (find the slug via the `fx::` tags when
72
+ you only have the FX name) and combine them.
73
+ - **Plugin gate — no plugin is touched before its memory is read.** Before the
74
+ first call that adds, sets, loads a preset for, writes MIDI to, or reads parameters
75
+ of a plugin (`add_fx`, `setup_fx_chain`, `set_fx_parameter`,
76
+ `set_multiple_fx_parameters`, `set_fx_preset`, `load_fx_chain`, MIDI for an
77
+ instrument track, take FX), look it up — every plugin, every time it is new to this
78
+ session, including ones the user named, ones already in the project and ones you
79
+ only meet while listing a chain. Never skip it because the plugin looks familiar.
80
+ Look up both layers: `list_builtin_knowledge { query: "<plugin name>" }` (or `tags:
81
+ ["fx::<FX name>"]`) / `get_builtin_knowledge { key: "plugins::{vendor}/{plugin}" }`,
82
+ and `memory.search` / `memory.read` of `user::plugins::{vendor}/{plugin}` (the user's
83
+ record wins). Then **follow the record**: its MIDI map and note ranges, parameter
84
+ scaling, recommended settings and gotchas decide what you do, and a setting you were
85
+ about to use that the record warns against is not used. Say it in one chat line
86
+ ("Recalled Odin x Ari Lite: notes <36 are keyswitches → transposing"). Keep a running
87
+ list of recalled plugins and don't re-read those. No record in either layer: say so
88
+ and carry on (or bootstrap it when the user asked for the plugin by name). LoreKit
89
+ not connected: say so once and use the built-in read only.
90
+ - **A record with an `extension::<name>` tag** means an opt-in extension drives that
91
+ plugin's internals (for a synth: wavetables, mod matrix, LFO shapes). When
92
+ `list_tool_categories` shows that extension's category, use its tools for anything
93
+ structural and keep `set_fx_parameter` for quick nudges; read the extension's
94
+ `read_*` tool before changing a patch. Not installed: say the structural part is out
95
+ of reach and offer `reaper-mcp extension add <name>`.
96
+ - **Asked to use a plugin you don't know?** Bootstrap it *before* mixing with it
97
+ (see the protocol): dispatch the `plugin-researcher` agent, which researches
98
+ the web, probes the plugin on a scratch track and writes its
99
+ `user::plugins::` record. If the agent isn't available, do those steps
100
+ yourself. Then read the record and use it. Refine it as you go.
101
+ - **On a durable plugin learning** (a verified param-index map, a setting the user
102
+ kept, a gotcha): read-merge-write that plugin's `user::` record (an overlay
103
+ when only a built-in record exists), adding a
104
+ **contextualized** note under `## Learned notes` — never an absolute rule.
105
+ - **At a correction point — write the lesson immediately, before your next action.**
106
+ A correction point is: the user reverted/rejected a change or said "no, that's
107
+ wrong"; a re-measure (meters/LUFS/correlation/crest) showed your change made it
108
+ worse; or you fell into a recurring trap. This is non-negotiable (see Hard
109
+ Rules) — do not defer it to the end, and **state in chat that you captured it**
110
+ (key + one-line takeaway). The dominant failure of this loop is *no capture at
111
+ all* — treat a silent skip as a bug.
112
+ - **End-of-session retrospective (always, even on a clean run).** Before your
113
+ final report, stop and ask: did the user correct or override me, did a
114
+ measurement surprise me, did I guess at something that paid off or nearly
115
+ didn't, should a lesson I already had have fired earlier? If anything surfaced,
116
+ write or UPDATE a lesson (dedup-search first; rewriting the same key bumps the
117
+ store's `seen_count`, never duplicates). Write nothing only when the
118
+ retrospective is genuinely empty — and say which.
119
+ - **When a lesson recurs (`seen_count >= 3`):** offer to promote it into the
120
+ Hard Rules below — the self-heal. Follow the protocol's entrenchment guards;
121
+ never let a lesson relax a hard rule.
122
+ - After any write, name the LoreKit key you wrote.
123
+ - **LoreKit not connected?** Say so once and carry on with the knowledge base and
124
+ general mixing knowledge.
125
+
126
+ ## Knowledge base (load on demand — don't preload)
127
+
128
+ Shipped baseline at the project `.claude/knowledge/` or `~/.claude/knowledge/`
129
+ (Glob to locate). Load only what the task needs (plugin knowledge is in LoreKit — see Memory):
130
+
131
+ - `genres/{genre}.md` — genre EQ/compression/LUFS conventions (if a genre is named)
132
+ - `workflows/{task}.md` — step-by-step procedures; map the request to one:
133
+ gain-staging · session-prep · vocal-chain · drum-bus · low-end · stereo-image ·
134
+ master-bus · stem-prep · delivery · section-levels · transient-lighting
135
+ - `reference/*.md` — frequencies, compression, metering, perceived-loudness, aesthetics-scoring,
136
+ common-mistakes (read these instead of guessing).
137
+
138
+ For analysis-only ("roast my mix"), defer to `/critique`. For final
139
+ loudness/limiting, defer to `/mastering`.
140
+
141
+ ## Workflow for any task
142
+
143
+ 1. **Recall** — read mixing lessons + relevant plugin memory (Memory above).
144
+ 2. **Understand** the request; load the matching `workflows/` + `genres/` docs.
145
+ 3. **Snapshot** — `snapshot_save { name: "before-{task}" }`.
146
+ 4. **Analyze** — `list_tracks` (in a big session filter it: `parent` = a folder
147
+ index or name, `nameContains`, `compact: true`, `offset`/`limit`).
148
+ - **Whole song / master** — `analyze_track_offline` on the master (-1) or the
149
+ bus in question: it renders once, needs no playback, works on folder
150
+ tracks, and returns integrated LUFS, LRA, true peak, crest, per-section
151
+ loudness (`sectionSeconds`), band balance, resonance and sibilance hints.
152
+ Pass `referencePath` (or `analyze_audio_file` on a reference song) for the
153
+ tonal and loudness delta against a reference. Resonance hints are most
154
+ meaningful on a single track; on a full mix they also catch sustained notes.
155
+ - **Balance between elements** — `list_regions` to find a section where every
156
+ compared element plays; then one `measure_tracks` call over it with the mix
157
+ bus and the elements (`lufs`, plus `spectrum` for tone). Add each track's
158
+ fader to its reading (the meters are pre-fader), express it as LU below the
159
+ mix bus, and compare against the stem reference points. Read spectra 3+
160
+ times (each is a ~0.5 s snapshot). A track that gave no data is under
161
+ `errors`, not zeros. `read_track_meters` is for headroom and clipping only,
162
+ never for balance.
163
+ - **Multi-mic sources** (snare top/bottom, kick in/out, overheads vs close
164
+ mics) — `measure_track_alignment`, then `set_track_property` `playOffsetMs`
165
+ = `suggestedPlayOffsetMs` and `phase` = `suggestedPhase` (both absolute:
166
+ they already include the track's current offset and polarity). With a
167
+ `warning` (correlation under 0.3) there is no suggestion: pick a range where
168
+ both tracks play the same hits and measure again.
169
+ 5. **Discover plugins** — `list_available_fx`; match against LoreKit plugin
170
+ records by `category::` + `fx::` tags and pick the highest `preference::`
171
+ (a `user::` record's preference overrides the built-in one).
172
+ 6. **Execute** — make changes, explaining each in audio terms.
173
+ 7. **Verify** — re-measure the same section the same way (LU, `kDb`); compare
174
+ against the reference points; revert if worse. For a judgement call (did this
175
+ change make the mix better?), A/B level-matched: `analyze_track_aesthetics`
176
+ on the same 30 s range before and after (it normalizes to -18 LUFS by
177
+ default — `normalizeLufs` — so a louder version does not score better just
178
+ for being louder). Only Production Quality (PQ) and Content Usefulness (CU)
179
+ judge a mix change; Content Enjoyment and Production Complexity follow the
180
+ arrangement and level. Treat PQ differences under ~0.1 as no change
181
+ (`reference/aesthetics-scoring.md`). Then ask the user to listen: their ear
182
+ has the final say.
183
+ - **Measure during playback, not by rendering**, while the user is in the
184
+ session: a render's progress window (and `open -a REAPER script.lua`)
185
+ takes focus from them. `measure_tracks`, the meters and the gain-trace
186
+ pair below need only playback; render the final deliverable when the user
187
+ says so.
188
+ - **Offer 2–3 variants for a judgement call** (e.g. drive/clipping/drum
189
+ level): save each as a snapshot, then switch between them *live* with one
190
+ `run_plan` that sets only the parameters that differ. A full-chunk
191
+ `snapshot_restore` reloads the plugins and can drop out mid-playback.
192
+ State each variant's LUFS, since the louder one wins a quick A/B by level
193
+ alone.
194
+ - **MIDI, notes or arrangement variants** (a drum groove, a bass line, a
195
+ different chorus) cannot go in snapshots, which store faders and FX
196
+ parameters, not items. Hand them to `/editing`, which compares whole
197
+ versions in fixed lanes; keep the mix side in snapshots here.
198
+ - **"It ducks with the full mix but not soloed"** is pumping. Measure it
199
+ with two `JS: reaper-mcp/mcp_gain_trace` instances: mode pre at the
200
+ start of the chain, mode post at the end, and the same slot on both. Read
201
+ the post instance's p5/p1/std after playback (std ≈1.0–1.3 dB is clean
202
+ on a loud metal bus, 1.5+ pumps). Check every external-sidechain
203
+ dynamic EQ/comp band and follow its key with `get_track_routing`
204
+ (receives). Kick→bass ducking deeper than about −3 dB pumps. A key from
205
+ the vocal can't cause ducking on drum hits.
206
+ `measure_tracks` removes these instances when it cleans up its own meters,
207
+ so read the trace before calling it.
208
+ 8. **Capture** — write any durable plugin learnings / process lessons (Memory).
209
+ Correction points are written *when they happen* (step 7), not saved for here.
210
+ 9. **Report** — first run the **end-of-session retrospective** (Memory) and write
211
+ any lesson it surfaces; then `snapshot_save { name: "after-{task}" }` and
212
+ summarize before/after measurements, **what you captured to memory (or that
213
+ nothing was)**, and suggested next steps.
214
+
215
+ ## Hard Rules
216
+
217
+ <!-- Promotion target: recurring process lessons graduate here via /mix-memory promote. -->
218
+
219
+ - **No plugin without its memory.** Before the first add/set/preset/MIDI call on any plugin this session, look up its built-in and `user::` records and follow them (plugin gate under Memory). Skipping the lookup because the plugin looks familiar is a bug.
220
+
221
+ - **Never skip the before-snapshot** — even for small changes. (Invariant.)
222
+ - **Capture the lesson at the correction point.** If the user reverts/rejects a
223
+ change or a re-measure is worse, write the process lesson *before your next
224
+ action* and say you did. Never end a session that had a correction without a
225
+ written lesson. (Invariant — the loop's whole value depends on it.)
226
+ - **Don't guess plugin names** — `search_fx` for the exact name.
227
+ - **Read `get_fx_parameters` before setting a parameter** — values are normalized
228
+ 0.0–1.0 and the mapping varies per plugin.
229
+ - **Meters are instantaneous** — play audio a few seconds before reading.
230
+ - **Keep bass mono below ~100 Hz** — check `read_track_correlation` on the bus
231
+ before any widening.
232
+ - **If a change sounds or measures worse, revert** to the before-snapshot.
233
+ - **A "flat" analyzer is not perceptually flat** — a balanced mix slopes gently
234
+ down from lows to highs.
235
+ - **Perceived values only, never raw.** Every balance or EQ claim cites LU
236
+ (post-fader, against the mix bus, same section) or `kDb` (same band across
237
+ tracks or a reference). Never judge or report balance from peak/RMS dBFS,
238
+ raw band `db`, raw FFT bins or fader positions alone, and never compare one
239
+ band with a different band of the same spectrum.
240
+ - **The user's ear is the finding.** When the user hears an imbalance, a
241
+ measurement that disagrees is suspect first: diff plugin parameters against
242
+ the before-snapshot, check for pre-fader readings, a bypassed meter or a
243
+ different section.
244
+ - **Section level changes are pooled automation items, never item gain.** When a
245
+ track is too loud or quiet in one part of the song, put automation items on its
246
+ Volume envelope with one pool per section type (`Vox Chorus` on every chorus),
247
+ so one edit moves every repeat (`workflows/section-levels.md`). Item gain and
248
+ take volume change what the FX chain receives; loose envelope points drift
249
+ apart between repeats.
250
+ - **Never prefix track names with their parent or role** ("A INST", "STEM DRUMS",
251
+ "LIVE OUT"). The folder already gives the context: a copy under `MIX A` is
252
+ `INST`, not `A INST`. Keep the user's names and duplicate names across folders;
253
+ target tracks by GUID or index instead of renaming them to make names unique.