Make audio plugins
for macOS & iOS.
juce-dev sets up everything you need to build an audio plugin — synth, effect, instrument, whatever you want. Name it, answer a few questions, and you've got a project that builds in Xcode. Add GPU-rendered UI with Visage, add an iOS target, and Claude knows how to help with each — a bundled juce-visage skill activates automatically when you're working on Visage UI.
Using Codex? See the Codex FAQ and the Codex juce-visage skill.
1. Checks your dev tools are installed (offers to set them up if not)
2. Loads your developer settings or walks you through first-time setup
3. Asks about optional features (GPU-rendered UI, crash reporting)
4. Creates the project with all your settings baked in
5. Sets up git, optionally creates a GitHub repo
6. Ready to build and open in Xcode
How It Works
Answer a few questions,
start building.
Starting a new audio plugin usually means wiring up build systems, configuring code signing, setting up project identifiers, and writing boilerplate. It's tedious before you write a single line of audio code.
juce-dev handles all of that. Give it a name, confirm your developer settings, pick your options, and you get a project that compiles immediately. If it's your first time, it checks your tools and walks you through setup.
Go cross-platform: Port between macOS, Windows, and Linux in any direction. The port command scans your project for platform-specific code, shows you exactly what needs to change, and applies the fixes — including building and testing on a remote VM over SSH. Started on Windows and want to ship on macOS? It handles that too, adding AU/AUv3 support, code signing, universal binaries, and everything else macOS needs. Porting to Linux? It adds Clang/Ninja build support, apt dependency installation, and a custom auto-updater — all tested on Ubuntu 24.04.
Context-aware assistance: If you add Visage GPU UI to your project, a bundled juce-visage skill automatically provides Claude with deep knowledge of Metal view embedding, event bridging, keyboard handling in DAW hosts, and more. No Visage? The skill stays out of the way — it only activates when relevant.
Want to go further? Use Chainer to describe what your plugin should do and let Claude build it for you.
What You Get
A complete project — not a tutorial, not a starter guide. A project that builds.
- Audio Unit, VST3, and Standalone app — all from one project
- Works in Logic Pro, Ableton Live, and other macOS DAWs
- Code signing and notarization config ready for distribution
- Optional GPU-rendered UI with Visage (Metal-accelerated)
- Optional iOS/iPadOS app target with auto-detected UI mode
- Bundled juce-visage skill — activates only when working on Visage UI
- Optional crash reporting for your users
- In-app auto-updates via Sparkle/WinSparkle
- CI/CD with proper installers — macOS .pkg and Windows Setup.exe, not just raw binaries
- One-command certificate export from Keychain to GitHub Secrets
- Port between macOS, Windows, and Linux — audit platform-specific code, fix, and test on a remote VM
- Git repo initialized, GitHub repo created if you want
- Checks your dev environment and installs missing tools
- Developer settings saved — next project is even faster
Installation
Two steps.
Requires Claude Code on macOS, Windows, or Linux. The plugin checks for other dependencies (Xcode/MSVC/Clang, CMake, Ninja) and helps you install anything missing.
/juce-dev:create
Commands
Full lifecycle.
Create, configure, build, port, ship. Start a project on one platform, easily port it to another. Each command does one thing well — combine with Chainer for automated workflows.
standalone with au, vst3, or all for other formats.
/juce-dev:build draft for a draft release instead. On Windows, creates a Setup.exe via Inno Setup.
setup-ios adds an iOS/iPadOS app target — it auto-detects Visage and creates a matching Metal UI with native touch handling. Both platforms share the same codebase. There's no --ios flag on create because the iOS target needs the project to exist first.
--verbose for full .env details.
#if JUCE_MAC guards, and MSVC flags. Can SSH to your Windows VM to build and test. Visage is fully cross-platform and is never flagged.
--doctor to validate your update chain.
--no-sign-macos / --no-sign-windows. Gracefully skips signing if certs aren't configured. After publish, download buttons on your GitHub Pages site are activated only for platforms with actual release assets, and the repo homepage URL is set automatically. If your .env is gitignored, CI falls back to .env.ci — a committed file with only non-secret values (PROJECT_NAME, versions, CI_PLATFORMS). Use status and logs to monitor runs. Use secrets to export signing certs from Keychain to GitHub Secrets.
gh-pages branch with a clean, responsive landing page — your plugin name, description, and download buttons. Supports light and dark mode. The generated index.html includes <!-- DOWNLOAD-MACOS-START --> / <!-- DOWNLOAD-MACOS-END --> marker comments around each download button. When you publish, update_download_links.sh replaces the content between these markers with active download links — "Coming Soon" stubs become real buttons. For pages without markers (e.g., custom designs), the script falls back to regex-based URL replacement, updating versioned release URLs in-place. Only platforms with actual release assets get active buttons (macOS checks for .pkg, Windows for Setup.exe or .zip, Linux for .tar.gz). The repo homepage URL is set to the GitHub Pages URL automatically, with custom domain detection. For private repos, the GitHub source link is omitted. Customize by editing index.html on the gh-pages branch — both marker-based and markerless pages are supported.
.env file so that /juce-dev:port and /juce-dev:build can SSH in to build and test on that platform. Use /juce-dev:vm list to see configured VMs. Supports Windows, Linux, and macOS VMs — Proxmox, UTM, Parallels, or any SSH-accessible machine.
Reference
All the options.
Every argument shown with an example. Most have smart defaults — you only need what's relevant to you.
What Gets Generated
From name
to namespace.
All the identifiers your plugin needs are derived automatically from the name you give it.
FAQ
Common questions.
JUCE is the most widely used C++ framework for building audio plugins and music software. It's used by companies like Ableton, ROLI, and hundreds of independent plugin developers. If you've used a software synth or effect in a DAW, there's a good chance it was built with JUCE.
juce-dev uses the JUCE-Plugin-Starter template — a pre-configured project setup that includes build scripts, version management, code signing, and distribution tooling on top of JUCE. You don't need to download JUCE separately; it's fetched automatically when you build.
Just Claude Code and a Mac. The plugin checks for everything else (Xcode command-line tools, Homebrew, CMake, GitHub CLI) and offers to install whatever's missing.
Optional: An Apple Developer account if you want to code-sign and distribute your plugin. You can skip this and add it later — you don't need it to build and test locally.
Anything that processes or generates audio on macOS: synthesizers, effects (delay, reverb, distortion), MIDI processors, samplers, drum machines, audio analyzers — whatever you can code in C++.
Each project builds three formats from one codebase: Audio Unit (for Logic Pro, GarageBand), VST3 (for Ableton, Reaper, etc.), and a Standalone app for testing without a DAW.
Yes. juce-dev sets up your project. To go from project to working plugin, install Chainer and describe what you want to build. Chainer will find the right tools and start implementing your idea.
For example: create a project with /juce-dev:create "Shimmer Delay", then tell Chainer you want "a stereo delay with pitch-shifted feedback and a wet/dry mix control." It handles the rest.
Visage is a GPU-accelerated UI framework for audio plugins on macOS. Instead of the standard JUCE graphics, Visage renders your plugin's interface using Metal at 60fps — smooth knobs, sliders, and animations with no CPU overhead.
It's optional. If you enable it, juce-dev sets up the framework, applies compatibility patches, and gives you a Visage-powered editor template to start from.
Bundled skill behavior: This plugin includes a juce-visage skill that is available after the plugin is installed. It works independently from command execution, so you don't need to run a separate command just to "turn it on." When you're working on Visage UI code, Claude uses that skill automatically for guidance (Metal view embedding, event bridging, DAW keyboard handling, popups/modals, iOS touch handling, and the Visage API).
If your JUCE project does not include Visage, the skill stays out of the way and won't push Visage-specific patterns. Add Visage first (for example via /juce-dev:create ... --visage or /juce-dev:setup-visage) to make that guidance relevant.
You can use Codex with the Codex juce-visage skill. It provides Visage-focused implementation guidance (Metal embedding, JUCE↔Visage event bridging, DAW keyboard behavior, popups/modals/dropdowns, iOS touch handling, and debugging patterns).
What it does not replace: the Codex skill is guidance-only. It does not provide the command workflow this plugin provides (no /juce-dev:create, no automated dependency checks/setup, no automatic Visage clone+patch flow, and no project bootstrapping/repo setup commands).
Recommended workflow: scaffold first using this plugin (in Claude Code) or the JUCE-Plugin-Starter, then use Codex + juce-visage for day-to-day Visage implementation and troubleshooting. If Visage is not added to the project, the skill stays out of the way.
Install the Codex skill:
This uses a sparse checkout to pull just the skill folder without downloading the entire repository.
Yes. Developer credentials (Apple ID, certificates, API keys) are stored in .env files which are listed in .gitignore. They're never committed or pushed to GitHub.
The template's .env is read-only — juce-dev reads your settings from it but never modifies it. All settings go to the new project's .env only.
Yes. Code signing settings (Apple ID, Team ID, certificates) are only needed when you're ready to distribute your plugin to other people. Skip them during setup and add them to your project's .env later.
You can build, test, and develop locally with no Apple Developer account at all.
Making an audio plugin from scratch means learning a build system, configuring Xcode, understanding plugin formats (AU vs VST3), setting up code signing, figuring out bundle identifiers, and writing a lot of boilerplate — all before you write a single line of audio code.
juce-dev skips all of that. You get a project that compiles and runs immediately. The build scripts handle everything from debug builds to signed, notarized releases you can distribute. You just focus on making your plugin do something interesting.
If you already have a JUCE workflow, this saves you the boilerplate of starting new projects. Beyond the template setup, you get:
• Build script with multiple actions: build.sh au debug, build.sh all publish, build.sh unsigned (fast installer testing), build.sh vst3 test (PluginVal integration)
• Code signing + notarization configured from .env — no manual Xcode setup
• Automatic versioning that increments on every build with proper AU version integers
• Visage integration with pre-applied patches for keyboard handling, popup positioning, FPS caps — plus a bundled juce-visage skill that helps Claude navigate the tricky parts (Metal view embedding, event bridging, DAW keyboard conflicts, iOS touch handling)
• GitHub release publishing with auto-download landing pages
• Shared JUCE cache at ~/.juce_cache/ so you don't re-download JUCE for each project
Use /juce-dev:build from Claude Code, or run build.sh directly. Both support the same targets and actions:
Local development:
• /juce-dev:build standalone — Build and launch standalone app
• /juce-dev:build au — Build Audio Unit
• /juce-dev:build vst3 — Build VST3
• /juce-dev:build au vst3 — Build multiple targets at once
Testing:
• /juce-dev:build all test — Build and validate with PluginVal
• /juce-dev:build unsigned — Create an unsigned installer for quick testing
Distribution:
• /juce-dev:build all sign — Build and code-sign
• /juce-dev:build all notarize — Build, sign, and notarize with Apple
• /juce-dev:build publish — Full pipeline: build, sign, notarize, and publish to GitHub Releases
• /juce-dev:build pkg — Signed installer without GitHub release
• /juce-dev:build uninstall — Remove all installed plugin components
Smart builds: The /juce-dev:build command auto-detects whether CMake regeneration is needed. If nothing changed in CMakeLists.txt or .env, it skips regeneration for faster builds.
Use /juce-dev:build --help for the full reference, or ./scripts/generate_and_open_xcode.sh to open the project in Xcode.
Port in either direction between macOS and Windows. Started on macOS? Use /juce-dev:port windows to scan for macOS-specific code and apply Windows-compatible fixes. Started on Windows? Use /juce-dev:port macos to scan for Windows-specific code and add macOS support (AU/AUv3 formats, universal binaries, code signing, notarization). Both directions can build and test on a remote VM over SSH. Linux support is coming soon.
The JUCE-Plugin-Starter template already includes cross-platform CMake configuration, a macOS build script (build.sh), and a Windows build script (build.ps1). The port command handles your project-specific code — the things you add on top of the template.
The build command (/juce-dev:build) also works on Windows and Linux if you're running Claude Code there — it detects the platform and uses the appropriate build script. Visage is fully cross-platform: Metal on macOS, Direct3D11 on Windows, Vulkan on Linux.
The port command supports porting between macOS, Windows, and Linux in any direction. It auto-detects your source platform and scans for the right patterns. It runs through four stages:
1. Audit — detects your source platform and scans for platform-specific code. macOS → Windows: finds Objective-C++, Cocoa/AppKit imports, CoreAudio/CoreMIDI, macOS paths. Windows → macOS: finds Win32 API calls (HWND, CreateWindow), COM interfaces, DirectX headers, MSVC pragmas, Windows registry access, .dll/.exe references. Categorizes by severity. Use --audit-only for just the report.
2. Plan — shows you the full list of changes and asks whether to apply all at once, go through them one by one, or export a plan to a markdown file.
3. Execute — creates a port/<platform> branch and applies fixes. To Windows: CMake conditionals, #if JUCE_MAC guards, MSVC flags, Windows build scripts. To macOS: #if JUCE_WINDOWS guards, AU/AUv3 format support, universal binary config (arm64;x86_64), code signing/notarization setup, macOS build scripts, Xcode project generation. To Linux: Clang/Ninja build config, apt dependency setup, custom auto-updater (pure JUCE, no external library), if(UNIX AND NOT APPLE) CMake blocks.
4. Test — optionally SSHs to your target VM, pushes the branch, runs the build there, and reports back. For macOS targets, also validates AU plugins with auval. If the build fails, it analyzes errors, fixes locally, pushes again, and retries. You can also trigger GitHub Actions CI instead.
Your project needs to be cloned on the VM as well — the port command pushes your branch to GitHub and pulls it on the VM via SSH.
You need SSH access to the target machine (a VM, a remote server, or another computer on your network). Add an SSH config entry in ~/.ssh/config:
Then register VMs with juce-dev:
Now you can port and test in one step:
The port command will SSH to your VM, pull the branch, build with the platform's toolchain, and report results. For macOS targets, it also validates AU plugins with auval. Your project repo needs to be cloned on the VM — the command pushes your branch to GitHub and pulls it remotely.
Use /juce-dev:vm list to see configured VMs, or /juce-dev:status for a full project overview.
Auto-updates use Sparkle on macOS, WinSparkle on Windows, and a custom appcast poller on Linux — the same Sparkle-compatible appcast XML feed works across all three platforms.
The updater UI lives in the standalone app only — you can't trigger an update from within a DAW plugin. On macOS, "Check for Updates..." appears in the app name menu. On Windows and Linux, it's in the Help menu. On Linux, the updater shows an alert with a download link — matching Linux conventions where users manage updates themselves.
When an update is available, the frameworks handle the download, progress UI, and installation. The update payload is a full product installer (PKG on macOS, Inno Setup on Windows) that replaces all plugin formats (AU, VST3, CLAP, Standalone) at once — no version skew between formats.
Installers are EdDSA-signed for integrity verification. Use /juce-dev:setup-updates to add auto-update support to your project, and --doctor to validate your update chain end-to-end.
If auto-updates are enabled, /juce-dev:build publish handles everything in a single command: build, code-sign, notarize, create the installer, EdDSA-sign it, upload to GitHub Releases, and generate the appcast XML that tells users a new version is available.
The appcast (appcast-macos.xml / appcast-windows.xml) is committed to your repo and served via raw.githubusercontent.com. It's always published last, after the installer is already uploaded — so users never see an update they can't download.
Manual "Check for Updates" picks up the new version immediately. Automatic background checks find it within 24 hours (configurable).
Everything is opt-in. If ENABLE_AUTO_UPDATE isn't set to true in your .env, the publish pipeline works exactly as before — no EdDSA signing, no appcast generation, no Sparkle/WinSparkle linking, no "Check for Updates" menu item. Zero impact on your build.
You can add auto-updates later at any time with /juce-dev:setup-updates.
Create a .env.ci file with only non-secret values and commit it. The CI workflow automatically falls back to .env.ci when .env doesn't exist.
.env.ci should contain: PROJECT_NAME, PROJECT_BUNDLE_ID, DEVELOPER_NAME, version numbers, GITHUB_USER, GITHUB_REPO, CI_PLATFORMS, and cert names (not secrets). Sensitive values like APPLE_ID and APP_SPECIFIC_PASSWORD stay as GitHub Secrets only.
Not recommended. The default single-repo pattern (source + releases + website in one repo) is simpler and works well for most plugins. It's what /juce-dev:build publish and /juce-dev:ci publish are built for.
If you have a specific reason to separate releases from source code (e.g., private source with a public download page), a split-repo pattern is possible but requires manual configuration: a separate release repo, a PAT for cross-repo access, and custom appcast setup. This is tracked as a future enhancement. Stick with the default unless you know you need it.
When you publish, the update_download_links.sh script checks the actual release assets on GitHub. If the release has a .pkg, the macOS button is activated. If it has a _Setup.exe (or .zip fallback), the Windows button is activated. If it has a .tar.gz, the Linux button is activated.
This means you can publish macOS-only first and add Windows later — each platform's button only appears when there's a real file to download. The script also updates versioned URLs in your README.md.
We use GitHub issue templates so you can report the right thing in the right place:
JUCE Dev (Claude Code plugin)
• Report a bug — command/setup/scaffolding issues
• Request a feature — plugin workflow improvements
juce-visage (Codex skill)
• Report a bug — incorrect or missing Codex skill guidance
• Request a feature — new Codex skill coverage or patterns
If you're an experienced C++ developer comfortable with CMake, Pamplejuce is probably the better choice. It's maintained by Sudara, a serious audio developer, and has a large community. It stays closer to standard CMake conventions and has excellent documentation.
juce-dev is designed for people who are newer to audio plugin development or want a more hands-off workflow. It handles prerequisites, scaffolding, building, signing, and publishing through natural language commands — you don't need to learn the underlying toolchain. It also adds features like in-app auto-updates, AI release notes, download pages, and diagnostic tooling that go beyond what a template typically provides.
Many of the build system patterns in JUCE Plugin Starter (the template juce-dev builds on) were inspired by Pamplejuce's approach to CI/CD, testing, and packaging. We're grateful for the example it set for the JUCE community.