Getting Started
Requirements
- macOS 15 (Sequoia) or later
- Apple Silicon (M-series)
- Any AUv3-compatible host (Logic Pro, GarageBand, Ableton Live, and more)
Installation
- Download the latest DMG
- Open the
.dmgand drag ConjureDSP into your Applications folder - Launch your DAW and load ConjureDSP as an Audio Unit effect on any track
Your First Effect
ConjureDSP comes with a built-in code editor. When you load the plugin, you’ll see the code editor with a default passthrough script.
Try replacing it with a simple gain effect:
from conjuredsp import db
from conjuredsp.dsp import db_to_gain
PARAMS = {
"gain": db(-24, 12, default=0),
}
def process(inputs, outputs, frame_count, sample_rate, params):
gain = db_to_gain(params["gain"])
for ch in range(len(inputs)):
outputs[ch][:frame_count] = inputs[ch][:frame_count] * gain The process function is called for every audio buffer. You receive:
- inputs / outputs — audio buffers, one per channel
- frame_count — number of valid samples in this buffer
- sample_rate — current sample rate (e.g., 44100)
- params — denormalized parameter values keyed by name
The conjuredsp library provides parameter builders (freq, db, time_ms, mix, etc.), filters, delay lines, oscillators, and DSP utilities. See Writing Effects and API Reference for details.
Factory Presets
ConjureDSP ships with factory presets covering common effects — gain, delay, chorus, compressor, EQ, and more. Each preset is available in both Python and Rust. Use them as working examples or starting points for your own effects.
Writing Effects
The process() Function
Every effect must define a process function that receives audio buffers and writes output samples:
def process(inputs, outputs, frame_count, sample_rate, params):
for ch in range(len(inputs)):
outputs[ch][:frame_count] = inputs[ch][:frame_count] In Rust, setup!() declares the buffers and exports required by the host, and ctx() creates a Context for safe buffer access.
Arguments
| Argument | Description |
|---|---|
| inputs / outputs | Audio buffers (float32), one per channel. In Python these are lists of numpy arrays. In Rust, use ctx.input(ch, fr) and ctx.set_output(ch, fr, val). |
| frame_count | Number of valid samples in this buffer |
| sample_rate | Current sample rate (e.g., 44100) |
| params | Denormalized parameter values keyed by name. In Rust, use ctx.param(INDEX). |
Transport
To access DAW transport information (tempo, beat position, etc.), add a transport parameter:
def process(inputs, outputs, frame_count, sample_rate, params, transport):
tempo = transport["tempo"] In Python, the transport parameter is opt-in — just add it as a sixth argument and ConjureDSP will pass it automatically.
| Key | Description |
|---|---|
tempo / T_TEMPO | Tempo in BPM |
beat / T_BEAT | Current beat position |
playing / T_PLAYING | 1.0 if playing, 0.0 if stopped |
time_sig_num / T_TIME_SIG_NUM | Time signature numerator |
time_sig_den / T_TIME_SIG_DEN | Time signature denominator |
sample_pos / T_SAMPLE_POS | Sample position in timeline |
Important Notes
inputsandoutputsare pre-allocated — write to them directly, don’t create new buffersprocess()runs on the real-time audio thread — avoid allocating memory and doing I/O- In Rust, persistent state uses
static mutwithunsafeblocks
Defining Parameters
Declare automatable parameters using the builder functions from conjuredsp:
from conjuredsp import freq, db, time_ms, mix, pct, toggle, ratio, choice, integer, param
PARAMS = {
"cutoff": freq(),
"gain": db(),
"time": time_ms(),
"mix": mix(),
"depth": pct(),
"bypass": toggle(),
"ratio": ratio(),
"mode": choice("Low", "Mid", "High"),
"bits": integer(2, 16, unit="bits", default=8),
"custom": param(0.5, 20, unit="Hz", default=5, curve="log"),
} Each key becomes a named parameter in the DAW. Values are denormalized to the real range (e.g., 20–20000 for freq()). In Python, access values with params["cutoff"]. In Rust, params! generates index constants for use with ctx.param(CUTOFF).
Parameter Builders
| Builder | Default Range | Unit | Curve | Notes |
|---|---|---|---|---|
freq() | 20 – 20000 | Hz | log | Audible frequency range |
db() | -60 – +12 | dB | linear | |
time_ms() | 0.1 – 1000 | ms | log | Fine control at short times |
pct() | 0 – 100 | % | linear | Default 50 |
mix() | 0.0 – 1.0 | linear | Wet/dry, default 0.5 | |
toggle() | 0 – 1 | linear | Renders as a switch | |
ratio() | 1 – 20 | :1 | linear | Compressor ratio, default 4 |
choice(...) | 0 – N-1 | linear | Dropdown menu; receives index as float | |
integer(min, max) | custom | linear | Stepped integer values; snaps automation to whole numbers | |
param(min, max) | custom | linear | Generic builder |
All builders accept overrides. In Python, use keyword arguments: freq(min=100, max=5000, default=440). In Rust, chain methods: freq().min(100.0).max(5000.0).default(440.0).
Note: choice() takes variadic args in Python — choice("A", "B", "C") — and a slice in Rust — choice(&["A", "B", "C"]).
Compilation
Python scripts run immediately when you save. Rust code is compiled on save using a bundled standalone Rust compiler that ships inside the plugin — there’s no cargo install step, no need for a system Rust toolchain, and no network round-trip during compilation. The compiler targets wasm32-wasip1 and the resulting WebAssembly module is executed by an embedded wasmtime runtime on the audio thread.
The first compile of a new script takes a couple of seconds; after that, ConjureDSP caches the compiled WebAssembly by the SHA256 of your source code, so re-running the same script is instant. Editing the script triggers a recompile only for the changed version, leaving the cache for previous versions intact.
The conjuredsp Rust library is pre-compiled as an rlib that ships with the plugin, so use conjuredsp::*; works out of the box with no Cargo.toml and no dependency resolution.
Installing Packages and Crates
ConjureDSP has a built-in package manager for both Python packages and Rust crates. Open the package pane from the plugin toolbar to:
- Browse and install any package from PyPI for use in your Python scripts
- Browse and install any crate from crates.io for use in your Rust scripts
- See what’s already installed and remove things you don’t need
Installed packages are available immediately to all your scripts — numpy, scipy, librosa, and the rest of the SciPy ecosystem on the Python side; any crate you can use on the Rust side. The package manager handles fetching, building, and signing on your behalf so the new code can run inside the plugin sandbox.
When to Use Rust
- CPU-intensive algorithms (convolution, physical modeling)
- Effects that need deterministic performance
- When Python’s overhead is noticeable at low buffer sizes
For most effects (gain, tremolo, filters, delay), Python is fast enough and much easier to iterate with.
Installing Packages
ConjureDSP bundles NumPy, SciPy, and the Python standard library for Python scripts, and a curated DSP prelude for Rust. When you want to reach beyond that — a favorite Python library for FFT analysis, or a Rust crate with a filter primitive you like — ConjureDSP can install it for you.
Opening the Package Manager
Click the Packages button (the shipping-box icon) in the preset toolbar. A popover opens with two tabs: Python and Rust.
Installing a Python Package
In the Python tab, type a package spec — for example pedalboard==0.9.16 — and click Install. Live search against PyPI suggests completions once you’ve typed a couple of characters.
Installed packages are available to every preset:
import pedalboard
from scipy import signal
Built-in packages (the standard library, NumPy, SciPy) are listed under Built-in; packages you’ve installed appear under User-installed.
Installing a Rust Crate
The Rust tab works the same way. Enter a crate spec like dasp = "0.11" and click Install. Live search queries crates.io.
First install takes a little longer — crates are compiled from source so they can run inside the plugin — but subsequent installs reuse the cached toolchain.
Use the crate in your scripts with a normal use statement:
use dasp::signal;
use conjuredsp::*;
Where Packages Live
Installed packages are shared across all presets, not isolated per-preset. They live inside the ConjureDSP application container and survive app updates.
Right-click any user-installed package and choose Remove to uninstall it. If an install fails, a View Log button appears next to the error — tap it to see the installer output.
Restrictions
- Python: must be compatible with the bundled Python runtime. Pure-Python and most common binary wheels work; the bundled
uvinstaller handles the resolution. - Rust: crates must compile without platform-specific C dependencies. Most DSP and math crates work out of the box.
API Reference
process()
Called for every audio buffer. Must write output samples to the output buffers.
def process(inputs, outputs, frame_count, sample_rate, params): Add a transport parameter for DAW transport info (opt-in in Python; always available via TRANSPORT_BUF in Rust):
| Key | Description |
|---|---|
tempo / T_TEMPO | Tempo in BPM |
beat / T_BEAT | Current beat position |
playing / T_PLAYING | 1.0 if playing, 0.0 if stopped |
time_sig_num / T_TIME_SIG_NUM | Time signature numerator |
time_sig_den / T_TIME_SIG_DEN | Time signature denominator |
sample_pos / T_SAMPLE_POS | Sample position in timeline |
Parameter Builders
from conjuredsp import freq, db, time_ms, mix, pct, toggle, ratio, choice, integer, param | Builder | Range | Unit | Curve | Default |
|---|---|---|---|---|
freq() | 20 – 20000 | Hz | log | 1000 |
db() | -60 – +12 | dB | linear | 0 |
time_ms() | 0.1 – 1000 | ms | log | 100 |
pct() | 0 – 100 | % | linear | 50 |
mix() | 0.0 – 1.0 | linear | 0.5 | |
toggle() | 0 – 1 | linear | 0 | |
ratio() | 1 – 20 | :1 | linear | 4 |
choice(...) | 0 – N-1 | linear | 0 | |
integer(min, max) | custom | linear | min | |
param(min, max) | custom | linear | min |
Override defaults with keyword args in Python (freq(min=100, default=440)) or chained methods in Rust (freq().min(100.0).default(440.0)). In Python, choice("A", "B", "C"); in Rust, choice(&["A", "B", "C"]). integer(min, max) is stepped — automation snaps to whole numbers, and the script receives an integer-valued float. In Python: integer(2, 16, unit="bits", default=8); in Rust: integer(2, 16).unit("bits").default(8).
Filters
from conjuredsp.filters import Biquad, BiquadCoeffs BiquadCoeffs — static methods returning filter coefficients:
| Method | Parameters |
|---|---|
lowpass(freq, q, sample_rate) | |
highpass(freq, q, sample_rate) | |
bandpass(freq, q, sample_rate) | |
notch(freq, q, sample_rate) | |
peak(freq, q, gain_db, sample_rate) | |
lowshelf(freq, q, gain_db, sample_rate) | |
highshelf(freq, q, gain_db, sample_rate) | |
allpass(freq, q, sample_rate) |
Biquad — stateful filter (direct form II transposed). Create one per channel.
| Method | Description |
|---|---|
Biquad() / Biquad::new() | Create a filter (passthrough by default) |
set_coeffs(coeffs) | Update coefficients (preserves state) |
process_sample(x) | Filter one sample, returns output |
reset() | Zero filter state |
In Rust, Biquad::new() is const fn — filters can be initialized in statics:
static mut FILTERS: [Biquad; 2] = [Biquad::new(); 2];
Delay Lines
from conjuredsp.buffers import DelayLine
dl = DelayLine(48000) # max delay in samples In Rust, DelayLine uses const generics for the buffer size and new() is const fn.
| Method | Description |
|---|---|
write(sample) | Write a sample and advance the write head |
read(delay_samples) | Read with linear interpolation |
read_cubic(delay_samples) | Read with Hermite cubic interpolation |
tap(delay_samples) | Read at integer delay (no interpolation) |
clear() | Zero the buffer and reset position |
Oscillators
from conjuredsp.osc import LFO, sine, triangle, saw, advance_phase LFO (Python) / Lfo (Rust) — stateful oscillator. Waveforms: sine, triangle, saw, square.
| Method | Description |
|---|---|
set_freq(freq) | Update frequency |
set_waveform(waveform) | Change waveform |
tick() | Advance one sample, returns value in [-1, 1] |
tick_n(n) | Advance n samples, returns array (Python: numpy) |
reset() | Reset phase to zero |
Construction differs between languages — Python’s LFO needs the sample rate and is typically lazily initialized inside process; Rust’s Lfo::new() is const fn and goes in a static mut:
_lfo = None
def process(inputs, outputs, frame_count, sample_rate, params):
global _lfo
if _lfo is None:
_lfo = LFO(sample_rate)
_lfo.set_freq(params["rate"])
... In Python, pass waveform names as strings: LFO(sample_rate, waveform="triangle") or lfo.set_waveform("saw"). In Rust, use the Waveform enum.
Stateless functions — take phase in [0, 1), return value in [-1, 1]:
sine(phase), triangle(phase), saw(phase), advance_phase(phase, freq, sample_rate)
DSP Utilities
from conjuredsp.dsp import db_to_gain, smooth_coeff, crossfade | Function | Description |
|---|---|
db_to_gain(db) | Decibels to linear gain (0 dB = 1.0) |
gain_to_db(gain) | Linear gain to decibels |
ms_to_samples(ms, sample_rate) | Milliseconds to sample count |
samples_to_ms(samples, sample_rate) | Sample count to milliseconds |
freq_to_period(freq, sample_rate) | Frequency to period in samples |
smooth_coeff(time_ms, sample_rate) | One-pole smoothing coefficient |
crossfade(dry, wet, mix, out, n) | Linear crossfade between buffers |
equal_power_crossfade(dry, wet, mix, out, n) | Equal-power crossfade |
soft_clip(x, drive=1.0) | Soft clipper (tanh saturation) |
lerp(a, b, t) | Linear interpolation |
Reporting Algorithmic Latency
Effects that introduce algorithmic latency (lookahead limiting, FFT windowing, oversampling) should declare it so the DAW can compensate and keep everything in sync.
Only report latency, not delay. The creative delay time in a delay effect is the point of the effect and should not be reported — the DAW would pull the whole track earlier to compensate, defeating the purpose. A delay effect can still declare latency for any lookahead or windowing it does internally; just don’t roll the delay time itself into that number.
LATENCY = 256 # samples of lookahead Python declares a module-level LATENCY constant in samples. Rust uses the latency!() macro, which generates a get_latency_samples() export. In both cases ConjureDSP reads the value at script-load time and forwards it to the DAW via AUAudioUnit.latency for automatic delay compensation.
Rust Extras
These features are specific to Rust and have no Python equivalent.
setup!()
Declares all required buffers, exports, and the ctx() helper. Must appear at the top of every Rust effect.
Context
Created by ctx() (generated by setup!()):
| Method | Returns | Description |
|---|---|---|
ctx.channels() | usize | Number of audio channels |
ctx.frames() | usize | Number of frames |
ctx.sample_rate() | f32 | Sample rate in Hz |
ctx.input(ch, fr) | f32 | Read input sample |
ctx.set_output(ch, fr, val) | Write output sample | |
ctx.param(INDEX) | f32 | Read parameter by index constant |
Persistent State
Rust effects use static mut for state that persists across process() callbacks. Constructors are const fn so they can be used in static initializers:
static mut FILTERS: [Biquad; 2] = [Biquad::new(); 2];
static mut DELAYS: [DelayLine<48000>; 2] = [DelayLine::new(); 2];
static mut LFO: Lfo = Lfo::new();
Available Libraries
The Python runtime includes numpy and scipy in addition to the conjuredsp package.
Neural Amp Modeling
from conjuredsp.nam import load_model
model = load_model("tone3000://TONE_ID/MODEL_ID") Load a .nam tone model. Accepts tone3000://tone_id/model_id, ~/relative, or absolute paths. See Neural Amp Modeling for full usage and examples.
Python model methods:
| Method | Description |
|---|---|
model.process(buffer, channel) | Process a float32 NumPy array for the given channel index. Returns a float32 array. |
model.reset() | Clear per-channel hidden state (LSTM models). |
Rust: nam!(path) is a module-level macro that registers nam_process(channel: usize, sample: f32) -> f32.
Neural Amp Modeling
Neural Amp Modeling (NAM) lets you load .nam tone models — deep-learning captures of amps, pedals, and full rigs — and run them as part of your ConjureDSP effects. ConjureDSP includes a built-in tone browser connected to tone3000.com, a community library where you can discover, download, and use thousands of tones without leaving your DAW.
The Tone Browser
Open the tone browser from the ConjureDSP plugin UI. From there you can:
- Search thousands of community tones by name, gear type (Amp, Pedal, Full Rig, Outboard, IR), or sort by trending, newest, or most downloaded.
- Browse your tones — see tones you’ve created or marked as favorites on tone3000.com.
- Download models in multiple sizes: Standard, Lite, Feather, or Nano — trading off quality for CPU load.
- Insert code — tap “Use” on any downloaded model and ConjureDSP inserts the
load_modelcall directly into your editor.
Sign in with your tone3000.com account to access your favorites and created tones. Authentication uses OAuth — no password is stored by ConjureDSP.
Loading a Model
from conjuredsp.nam import load_model
model = load_model("tone3000://TONE_ID/MODEL_ID") TONE_ID and MODEL_ID are filled in automatically when you tap “Use” in the tone browser. You can also pass a local file path:
model = load_model("~/my-tones/jcm800.nam") Processing Audio
Call model.process() inside your process function. The model is stateful — pass the channel index so each channel gets independent state:
from conjuredsp.nam import load_model
from conjuredsp import db, mix
model = load_model("tone3000://TONE_ID/MODEL_ID")
PARAMS = {
"input_gain": db(min=-60, max=12, default=0),
"mix": mix(),
}
def process(inputs, outputs, frame_count, sample_rate, params):
gain = 10 ** (params["input_gain"] / 20.0)
mix_val = params["mix"]
for ch in range(len(inputs)):
dry = inputs[ch][:frame_count]
wet = model.process(dry * gain, ch)
outputs[ch][:frame_count] = dry * (1.0 - mix_val) + wet * mix_val API Reference
load_model() / nam!()
| Python | Rust | |
|---|---|---|
| Import | from conjuredsp.nam import load_model | use conjuredsp::*; |
| Load | model = load_model(path) | nam!(path) (module-level macro) |
| Process | model.process(buffer, channel) | nam_process(channel, sample) |
| Reset state | model.reset() | — |
load_model(path) — loads a .nam file. Supported path formats:
| Format | Example |
|---|---|
| tone3000 URL | "tone3000://abc123/def456" |
| Home-relative | "~/my-tones/jcm800.nam" |
| Absolute path | "/Users/me/tones/jcm800.nam" |
model.process(buffer, channel) (Python) — processes a NumPy float32 array for the given channel index. Returns a float32 array of the same length.
model.reset() (Python) — clears per-channel state (LSTM models only). Call this when playback restarts to avoid artifacts from stale hidden state.
nam!(path) (Rust) — module-level macro that loads the model at startup and registers nam_process(channel: usize, sample: f32) -> f32 for use inside process.
Supported Architectures
ConjureDSP supports both WaveNet and LSTM architectures.
tone3000:// URL Scheme
Downloaded tones are stored locally in the ConjureDSP app container. The tone3000://TONE_ID/MODEL_ID path is resolved automatically — no manual file management needed. Tones remain available offline after download.
AI-Assisted Coding
ConjureDSP is built around the idea that you should be able to describe an audio effect in plain English and hear it on your track seconds later. The AI does the typing; you do the listening.
The important part: ConjureDSP itself doesn’t host or route any AI. There’s no ConjureDSP-branded mode. You select your preferred coding assistant, and ConjureDSP plugs into it.
There are two ways to do this.
Option 1: Integrated AI connection
ConjureDSP ships with a full terminal pane inside the plugin window. You can run any terminal-based AI coding agent in it. ConjureDSP has first-class auto-launch support for Claude Code, Codex CLI, and Gemini CLI, and any other tool (Aider, a plain shell, etc.) works via the manual picker option. The agent reads your current script, writes new DSP code, hot-reloads it, and you hear the change on the track. It can also tweak parameters, save presets, and check the audio state.
Picking an agent
On first launch, ConjureDSP looks for supported agents on your PATH. If it finds exactly one, it auto-launches that agent. If it finds more than one, you get a numbered picker to choose — the choice is remembered for next time.
You can switch agents from the terminal at any time with:
conjure-use-claude— auto-launch Claude Code next sessionconjure-use-gemini— auto-launch Gemini CLI next sessionconjure-use-codex— auto-launch Codex CLI next sessionconjure-use-manual— skip auto-launch; drop to a plain shell so you can start whatever tool you want
The same preference can be edited in Settings → Terminal, which also has a Relaunch terminal button to apply the change immediately.
MCP, automatically
Under the hood, ConjureDSP exposes itself as an MCP server (Model Context Protocol) with 12 tools:
compile_and_run·get_script·get_errorset_parameter·get_parameters·get_audio_statelist_presets·save_preset·toggle_bypassget_docs·list_packages·list_tones
Whichever agent you pick, ConjureDSP wires up the MCP connection automatically before launching it — no manual config. The Terminal settings tab shows each agent’s MCP status so you can confirm it’s connected. Any other MCP-compatible client can connect the same way; the connection is local, over a loopback socket on your machine.
Option 2: Copy-paste prompt helper
If you’d rather not run an agent at all, ConjureDSP has a built-in prompt helper. You type what you want to build, and ConjureDSP assembles a self-contained prompt that bundles:
- The relevant API documentation
- Your current script (optional)
- Your description and target language
Copy it, paste it into Claude.ai, ChatGPT, Gemini, or any chatbot you already use, then paste the response back into the editor and hit Run. Same loop, no subscription required.
Exporting as a Standalone AU
Once you’ve dialed in a preset you’re happy with, you can export it as its own AUv3 plugin. The result is a self-contained Audio Unit that shows up in your DAW’s plugin list like any other effect.
Exporting a Preset
- Load or save the preset you want to export.
- Click the Export button (the share icon) in the plugin toolbar. A popover titled Export as Standalone AU opens.
- Enter an Effect name — this is what your DAW will display.
- Click Export.
ConjureDSP builds the plugin in the background and installs it to ~/Library/Application Support/ConjureDSP/Exports/ when it’s done. Your DAW will pick it up on the next plugin rescan.
NAM Tones in Exported Presets
If your preset loads a NAM tone model (load_model in Python, nam! in Rust), the tone file is bundled into the exported plugin so it keeps working on machines that don’t have ConjureDSP installed.
Because you’re redistributing that tone file, the exporter asks you to certify one of:
- I have permission from the tone creator to redistribute this file.
- I am exporting for personal use only.
Pick whichever applies before the Export button becomes available.
What Ships in the Plugin
Exported plugins are fully self-contained:
- Python presets ship their source plus the Python runtime needed to execute it.
- Rust presets ship a pre-compiled binary — nothing is compiled at load time.
Either way, exported plugins load instantly in your DAW and run independently of ConjureDSP.
Updating an Exported Plugin
Each exported AU is a snapshot of the preset at export time. Editing the preset inside ConjureDSP doesn’t update plugins you’ve already exported — re-export to pick up changes. The new build overwrites the previous one under the same effect name.
Syncing Presets with GitHub
Every preset you save in ConjureDSP is already a git commit under the hood. If you want to back those commits up — or share presets with another machine or another person — point ConjureDSP at a GitHub repository and it’ll push automatically on every save.
Setting Up Sync
Open the preset toolbar, click the Settings (gear) icon, and select the Sync tab.
1. Personal Access Token
Paste a GitHub personal access token and click Save. The token is stored in your macOS Keychain and is only used when pushing to a remote — local commits don’t require one.
Two token types work:
- Classic PAT (starts with
ghp_) — create at GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic), withreposcope. - Fine-grained PAT (starts with
github_pat_) — create at GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens, scoped to your presets repository with Contents: Read and write.
2. Commit Messages
Choose how commits are named on save:
- Always prompt for message on save — ConjureDSP pops a dialog on every save.
- Always use timestamp — commits are named with an ISO timestamp. No prompt.
3. Remote
Enter your repository URL (e.g., https://github.com/you/my-conjuredsp-presets.git) and click Set remote. After that, every saved preset pushes automatically with a short debounce, so rapid saves batch into a single push.
Use Push now to force a push immediately, or Clear remote to stop auto-push without deleting any commits.
Repository Format
ConjureDSP expects — and creates, on first push — this layout at the root of the repository:
conjuredsp.json # { "version": 1, "type": "presets" }
python/
gain.py
gain_metadata.json # optional — name, category, author, description
...
rust/
tremolo.rs
tremolo_metadata.json
...
You can edit files directly on GitHub or on another machine; ConjureDSP picks up changes on its next pull.
What Gets Synced
- User presets — yes. Anything you save yourself.
- Factory presets — no. These ship with the app.
- Package manager state — no. Install packages separately on each machine.
Where Presets Live Locally
User presets live in ConjureDSP’s container at ~/Library/Group Containers/group.com.MichaelJancsy.ConjureDSP/Presets/. That directory is itself a git repository, so you can inspect history from the command line if you want:
cd ~/Library/Group\ Containers/group.com.MichaelJancsy.ConjureDSP/Presets
git log --oneline
Push Status
The Sync tab shows the last push result at a glance: Never pushed, Last push: N minutes ago, or Push failed: <error>. If a push fails — bad token, network drop, rejected branch — the commit stays local. Fix the problem and hit Push now to retry.
Troubleshooting
If something isn’t behaving the way you expect, this page is the first place to look. If you don’t see your issue here, email conjuredsp@gmail.com.
ConjureDSP doesn’t appear in my DAW’s plugin list
macOS keeps an Audio Unit cache that occasionally gets out of sync after an install. The fix:
- Quit your DAW.
- Open Terminal and run:
killall -9 AudioComponentRegistrar - Reopen your DAW. Most DAWs will trigger a fresh AU scan automatically. In Logic Pro you can force it from Logic Pro → Settings → Plug-In Manager → Reset & Rescan Selection.
If it still doesn’t show up, make sure ConjureDSP is in /Applications (not your Downloads folder).
I loaded the plugin but I hear silence
The most common reason: you’re running the Demo and its audition budget has elapsed. The Demo gives you about a minute of active audio playback per plugin instance — silent passages don’t count against it, so the clock only ticks while something is actually coming out of the plugin. Once the budget is used up, output is muted until you reset it.
To get more demo time, click Restart Demo in the plugin’s subscription settings pane. This zeroes the counter and gives you another minute of active playback. Or grab a license to remove the limit entirely.
If you’re running the Licensed version and still hearing silence, check:
- The bypass toggle in the plugin header isn’t on
- Your script’s
process()function actually writes to the output buffers - The track itself has signal coming in (try the built-in spectrogram — if input is moving but output isn’t, the script is the issue)
My Rust code takes a long time to compile the first time
That’s expected. ConjureDSP ships its own standalone rustc and compiles your code to WebAssembly the first time it sees a particular script. After that, the compiled WASM is cached by the SHA256 of your source, so subsequent runs of the same code are instant. Editing the script triggers a recompile only for the changed version.
The integrated terminal won’t connect
The terminal runs in a small companion app called ConjureDSPTerminal that ships inside the main app bundle. The plugin tries to auto-launch it when you open the terminal pane, but if it doesn’t connect:
- Look for a Launch Terminal button in the terminal pane — this re-triggers the auto-launch. You should see ConjureDSPTerminal appear in your Dock a moment later.
- If that doesn’t work, quit and reload the plugin in your DAW. A fresh instance retries the auto-launch from scratch.
- As a manual fallback, you can open the companion app directly at
/Applications/ConjureDSP.app/Contents/Library/ConjureDSPTerminal.app.
Why a companion app? AU plugins run inside a sandbox managed by your DAW, and that sandbox can’t fork the Claude Code CLI directly. The companion app sits outside the sandbox and relays input and output to the terminal pane in the plugin window.
Monaco editor / code editor doesn’t load
This usually means a network call to the bundled editor assets failed at install time. Reinstalling from the latest DMG fixes it. If that doesn’t work, email us with your macOS version and DAW name.
NAM / tone3000 questions
See the Neural Amp Modeling page for which model architectures are supported (WaveNet and LSTM at the time of writing) and how the in-plugin tone browser works.
My preset works in ConjureDSP but the exported standalone plugin sounds different
Exported plugins use the same Python or Rust runtime as ConjureDSP, but the parameter ranges and defaults are baked in at export time. If you’re getting different output, double-check that the parameter values in the standalone plugin match the preset you exported from. If the difference is in the audio itself (not parameters), email us with both files attached so we can reproduce.