Claude Code Plugin¶
Pulp includes a Claude Code plugin that provides commands, skills, and hooks for the full audio plugin development lifecycle. If you're using Claude Code, we highly recommend installing it.
CLI expectations¶
As of Pulp v0.78.1, the user-facing pulp CLI is the Rust binary. Source
builds produce ./build/pulp, while release installers place pulp and the
C++ fallthrough delegate pulp-cpp side by side. Slash commands and skills
should use pulp on PATH, or ./build/pulp inside a source build. Use
pulp-cpp only for rollback/debug comparisons.
For PR/shipping workflows, agents and humans should use shipyard pr. Direct
gh pr create is a manual bypass only because it can leave the PR outside
Shipyard-managed tracking state. pulp pr defaults to Shipyard, while
pulp config set pr.workflow github and manual are explicit local opt-outs
for humans who do not want Shipyard in their checkout.
Installation¶
From the marketplace (recommended)¶
Install the Pulp CLI first so pulp and pulp-mcp are on $PATH, then add
the Claude Code plugin from the public marketplace:
# 1. Install the Pulp CLI and MCP binary.
curl -fsSL https://www.generouscorp.com/pulp/install.sh | sh
# 2. Add the marketplace and install the plugin.
claude plugin marketplace add Generous-Corp/pulp
claude plugin install pulp
Then restart Claude Code or run /reload-plugins to activate.
From a local clone (source-tree development)¶
If you're developing Pulp from a checkout, or testing local plugin changes, install the plugin from that clone instead:
# Clone the repository.
git clone https://github.com/Generous-Corp/pulp.git
cd pulp
# Install the checkout into Claude Code.
claude plugin add "$PWD"
Then restart Claude Code or run /reload-plugins to activate.
What You Get¶
Slash Commands¶
The plugin loads commands from .claude/commands; this table lists common
examples rather than the full source-tree inventory.
| Command | Description |
|---|---|
/build |
Build the project (configure + compile) |
/test [pattern] |
Run tests, optionally filtered by pattern |
/create <name> |
Scaffold a new plugin or app project |
/status |
Show project status, build state, configuration |
/validate |
Run plugin format validators and validation reports |
/seq |
Inspect, validate, edit, explain, import, or consent-gated export of a timeline project |
/design [style] |
AI-driven design session with natural language |
/ship |
Sign, notarize, and package for distribution |
/import-design |
Import from Figma, Stitch, v0, Pencil, Claude Design, DESIGN.md, or React JSX |
/kit |
Search, inspect, plan, apply, remove, pack, or scaffold Pulp kits |
/content |
Validate, install, update, list, rescan, remove, or reveal data-only content packs |
/version |
Show, bump, or check version consistency |
Skills¶
The plugin loads skills from .agents/skills. Skills activate automatically
based on context, and the table below lists common examples rather than the full
source-tree inventory.
| Skill | Activates when you... |
|---|---|
| ci | Say "ship this", "create a PR", "run CI", "merge to main" — uses shipyard pr for PR creation, tracking, cross-platform validation, and merge-on-green |
| engine | Ask about JS engines, Three.js performance, switching to V8/JSC |
| import-design | Want to import a design from Figma or other tools |
| content | Want to validate or install preset/theme/sample/wavetable content packs |
| webview-ui | Want to build a WebView-based UI panel |
Hooks¶
The plugin includes hooks that run automatically:
- docs-reminder — When you modify files in
core/,examples/, ortools/cli/, reminds you to update documentation manifests - cli-plugin-sync — When you modify the CLI or MCP server, reminds you to check if the plugin commands and skills need matching updates
- inject-claude-prefs (
SessionStart) — Readsclaude.send_user_filefrom~/.pulp/config.toml(default on) and, when enabled, tells the agent to surface generated image/file artifacts with theSendUserFiletool so they embed in the Claude app instead of being printed as a bare path. Toggle withpulp config set claude.send_user_file off(andonto re-enable).
MCP server¶
The plugin ships an MCP (Model Context Protocol) server — pulp-mcp — that
exposes Pulp operations as callable tools, so Claude Code (and other MCP
clients) can drive them in one turn instead of multiple shell calls.
| Category | Tools |
|---|---|
| Build / test / status | pulp_build, pulp_test, pulp_status, pulp_validate (screenshot=true for validation editor PNGs), pulp_create, pulp_docs_check, pulp_docs_search |
| UI rendering + interaction | pulp_screenshot (render demo/script UI fixtures to PNG), pulp_simulate_click, pulp_get_view_tree |
| Development Inspector | Installed pulp_inspect_* clients discover and authenticate to explicitly inspector-enabled standalone sessions. pulp_motion_* and live-session pulp_trace_* wrappers still require host support; offline trace query remains usable without a live session. |
| Audio model / WAV-first excerpt-find / live probe/scope JSON / third-party plugin inspection + offline render / advisory before-after compare | pulp_audio_model_list, pulp_audio_model_status, pulp_audio_model_activate, pulp_audio_excerpt_find, pulp_audio_read_bundle, pulp_audio_probe_json, pulp_audio_scope, pulp_audio_plugin_inspect, pulp_audio_render, pulp_audio_compare |
| Timeline project editing, history, rendering + interchange | pulp_timeline_project_open, pulp_timeline_command_apply, pulp_timeline_diff, pulp_timeline_undo, pulp_timeline_redo, pulp_timeline_validate, pulp_timeline_explain, pulp_timeline_render, pulp_timeline_export, pulp_timeline_import |
| Kit manifests | pulp_kit, pulp_kit_search, pulp_kit_validate, pulp_kit_inspect, pulp_kit_plan, pulp_kit_verify, pulp_kit_apply, pulp_kit_remove, pulp_kit_pack, pulp_kit_publish_check, pulp_kit_init |
| Content packs | pulp_content, pulp_content_validate, pulp_content_preview, pulp_content_install, pulp_content_update, pulp_content_list, pulp_content_rescan, pulp_content_remove, pulp_content_reveal |
For a standalone synth or transport fixture, first confirm that test.input
is effective, then use the bounded typed commands with the same exact selectors:
pulp inspect inject-midi --kind note_on --channel 1 --note 60 --velocity 100 \
--duration-ms 250 --json \
--session SESSION_ID --instance INSTANCE_ID --publication PUBLICATION_ID
pulp inspect set-transport --playing true --position-samples 0 --tempo-bpm 120 --json \
--session SESSION_ID --instance INSTANCE_ID --publication PUBLICATION_ID
The matching MCP tools are pulp_inspect_inject_midi and
pulp_inspect_set_transport. MIDI is limited to note-on/off with channels
1–16 and byte-range note/velocity values. Transport is an idempotent partial
standalone update. Raw MIDI, SysEx, files, presets, generic UI scripting, and
Runtime.evaluate are outside test.input. Injected notes are released on
controller lease loss, disconnect, or session teardown. A note_on requires a
1–2000 ms duration; the client sends its matching note-off on the same
connection before releasing the one-shot lease.
Use pulp_audio_probe_json as the quick live-health check for a standalone
target. It runs the existing pulp run --audio-probe-json path through
pulp-mcp and returns structured peak/RMS, callback, clip, NaN/Inf, and device
stress counters. It is not a new MCP server and it is not an offline signal
quality analyzer; switch to Audio Doctor or a scenario render when the live
snapshot is healthy but the audio still sounds wrong.
Use pulp_audio_scope when an agent needs real sample-window acquisition and
measurements instead of scalar probe counters. Live target mode may open the
standalone audio device; input_wav mode is speakerless/offline and can also
write a PNG trace artifact for review. Both modes return pulp.audio.scope.v1
structured JSON.
Use pulp_audio_plugin_inspect first when an agent does not know a third-party
plugin's host API. It loads the bundle in a disposable worker and returns every
parameter ID, plain range, default/current value and flag, plus buses, latency,
and tail. Feed those IDs to pulp_audio_render, which performs a second isolated
offline run (no DAW or audio device) and returns audio-analysis metrics. It can
warm up asynchronous plugins, apply one initial parameter and settle before
capture, drive one sample-timed param/midi event, append a tail, and retain a
high-resolution WAV. Use the CLI when a scenario needs repeatable parameters or
MIDI events.
Use pulp_audio_compare to get an advisory before/after judgment between two
WAVs (measure → compare → judge) through pulp audio compare. It delegates to the
opt-in Audio Quality Lab tool, level-matches, runs one axis (profile), and
returns the typed quality_lab.compare.v1 report (evidence envelope + a verdict
like regression_suspected / material_change_detected). It is advisory, never a
gate; set reference_role: golden when the reference is the known-good baseline.
Requires pulp tool install audio-quality-lab. For an exact pass/fail diff use
the deterministic pulp audio validate compare surface instead.
The inspection/render/validate workflow is built into Pulp. Audio Quality Lab is only the richer advisory comparison step; its absence never blocks inspection or rendering and the compare tool returns an explicit install command.
The ten timeline tools are generated from the committed timeline schema
manifest. Seven retain stateless timeline-tool entry points; diff, undo, and
redo are MCP-local DocumentSession operations with no pulp seq session
subcommands.
Opening a project returns a bounded in-process session identifier;
pass it to command application, diff, undo, and redo to iterate without
re-reading whole documents. Command application accepts only the generated
typed command envelopes. The MCP process admits at most 32 sessions and applies
a 64 MiB aggregate admission charge equal to twice each canonical JSON size plus
its fixed history reservation. This deterministic charge is a resource proxy,
not a direct heap measurement. Each complete encoded result is independently
capped at 64 MiB, and the oldest session is evicted first when admitting a
session would cross the count or aggregate charge. Sessions expire on eviction or process
restart, and a session whose bounded journal is full refuses the next edit
atomically. Diff reports the engine's exact dirty set and before/after revisions
for the latest successful apply, undo, or redo transition; it is not a
since-revision query. Use
pulp_timeline_render for deterministic Float32 WAV output, then optionally pass
before/after renders to pulp_audio_compare for an advisory judgment. Export
requires explicit consent for every reported lossy concept; its accepted-loss
enum is generated from the committed interchange concept authority and offers
no force or accept-all escape hatch. Call it first with outputless
plan_only: true (and no accept_losses) to receive the canonical manifest and
required_consent without writing; publishing requires output; refusal
and successful export return the same manifest shape. SMF export publishes a
new artifact directory and SMF import consumes a MIDI file. DAWproject export
atomically publishes a standard .dawproject ZIP, and DAWproject import consumes
that container while rejecting unsafe entries before sealing referenced media
into the new canonical project directory.
The kit and content MCP tools mirror the CLI trust model. pulp_kit_* tools inspect, plan, verify, and apply local project-transforming artifacts only after review; pulp_content_* tools validate, preview, and install data-only packs for an explicit plugin. Curated dependency packages stay on pulp add <name>.
Setup¶
The plugin and project-local .mcp.json invoke the explicit path in
PULP_MCP_BINARY instead of relying on Claude Code to inherit an
interactive-shell PATH. The CLI installers persist that variable with the
full pulp-mcp path. The same variable selects non-default installs and source
builds on every platform without a platform shell wrapper. Restart the shell
after installation so Claude Code inherits it.
Source contributors who want Claude Code to use the checkout build can prepend its output directory when starting Claude Code:
On Windows, set PULP_MCP_BINARY to the built .exe (including the
configuration subdirectory for a multi-config generator) before launching
Claude Code. If that path is absent, Claude Code reports the failed server
directly.
The /status command and pulp_status MCP tool include the effective
pulp import-design defaults, so Claude Code can see whether a checkout is
using the shipped live/js default or a local baked IR/C++ preference.
One MCP endpoint in both installation modes¶
This means marketplace users receive both the Pulp skills and the MCP tools.
They still need the Pulp CLI installation, which includes pulp-mcp and
configures PULP_MCP_BINARY. The root
.mcp.json is also the project-local configuration, and both modes resolve the
same command. Claude Code therefore identifies them as the same endpoint when
an installed plugin is used from a Pulp checkout instead of starting two Pulp
servers.
Plugin Structure¶
pulp/
├── .mcp.json # MCP wiring for checkout and marketplace use
├── .claude-plugin/
│ └── plugin.json # Plugin manifest
├── .claude/
│ ├── commands/ # Slash commands
│ │ ├── build.md
│ │ ├── test.md
│ │ ├── create.md
│ │ ├── status.md
│ │ ├── validate.md
│ │ ├── design.md
│ │ ├── ship.md
│ │ ├── import-design.md
│ │ ├── kit.md
│ │ └── content.md
│ └── settings.json # Hook configuration
├── .agents/
│ └── skills/ # Shared skills (Claude Code + Codex)
│ ├── ci/
│ ├── content/
│ ├── engine/
│ ├── import-design/
│ ├── kits/
│ └── webview-ui/
└── hooks/
├── hooks.json # Hook definitions
└── scripts/
├── docs-reminder.sh
└── cli-plugin-sync.sh
Skills live in .agents/skills/ so they're shared between Claude Code and Codex CLI. Both agents read from the same location, and the /kit and /content slash commands point agents at the same inspect/preview/approve/apply workflows documented here.
Kit Manifests¶
The plugin includes a kits skill for reusable Pulp-native source, UI, template, validation, graph, and native-component artifacts.
Why it matters:
- developers can share real Pulp building blocks instead of copy-pasted examples;
- users see capabilities, licenses, files, and project changes before approval;
- agents can inspect and plan without running untrusted package code.
pulp kit validate <path>
pulp kit search <query> --root <dir> --lane kit --json
pulp kit search <query> --root <dir> --lane content --json
pulp kit inspect <path> --json
pulp kit plan <path> --json
pulp kit verify <path> --json
pulp kit verify <path> --execute-screenshots --json
pulp kit apply <path> --yes
pulp kit remove <kit-id> --yes
pulp kit pack <path> --output <file>
pulp kit publish <path> --dry-run --json
pulp kit publish <path> --dry-run --registry-manifest <file> --json
pulp kit init --kind source --id com.example.my-kit
pulp create "Kit Gain" --template <template-kit-dir> --no-build --ci
Keep the trust boundary simple:
pulp add <name>is only for curated dependency packages from the Pulp registry.pulp kit ...is for local or external artifacts that may transform a project.pulp kit searchis local discovery only. It does not fetch and does not make a result trusted.content-packmanifests can be searched, validated, and inspected for classification, butpulp kit plan/apply/publishrejects them. Usepulp content ...for data-only packs.
The agent workflow is inspect, plan, verify, approve, apply. Validate/inspect/plan/pack/publish dry-run are metadata-only: no package CMake, JavaScript, scripts, dynamic libraries, remote search, or content installers. .pulpkit and .pulpcontent archives must include files.sha256.json; every payload file must be listed and hash-matched before the manifest is trusted.
Validation is valuable because it catches license, SDK, C++ standard, internal-module, tampered-evidence, and missing-review problems before any project CMake changes. pulp kit apply --yes writes only reviewed owned files (.pulp/kits.lock.json, generated CMake scaffolding, and declared files under pulp-kits/<kit-id>/). Dependency packages declared by a kit resolve only through the existing curated pulp add <id> path. pulp create --template <template-kit-dir> validates an explicit local template kit and never installs dependencies implicitly.
Evidence rules to surface before apply:
- Agent-authored kits need
authoring.humanReview.reviewed = truebefore publish dry-run can pass. - Template kits need
validation.generatedProjectDiffs. - UI kits need screenshot profiles/reports; run
pulp kit verifyafter plan review, and use--execute-screenshotsonly when rendered artifacts are explicitly needed. - Graph/native kits need exported fixtures/files plus explicit realtime claims (
processSafe,allocatesInProcess,locksInProcess); verification must not load dynamic libraries.
Content Packs¶
The plugin includes a content skill for data-only packs installed into an existing plugin's user content directory.
Why it matters:
- plugin authors ship presets, themes, samples, and wavetables without custom installers;
- users can validate, see reload/restart expectations, and remove packs without losing their own presets;
- agents match packs to plugins through runtime capabilities before install.
pulp content validate <path> --json
pulp content preview <path> --plugin-runtime <manifest> --json
pulp content install <path> --plugin <plugin-id> --yes
pulp content update <path> --plugin <plugin-id> --yes
pulp content list --plugin <plugin-id> --json
pulp content rescan --json
pulp content reveal <package-id> --plugin <plugin-id> --version <version>
pulp content remove <package-id> --plugin <plugin-id> --version <version> --yes
Content packs are not curated dependency packages and do not transform projects. The workflow is validate, preview compatibility and reload policy, approve, install or update. Install/update/remove require explicit approval and never execute package CMake, JavaScript, scripts, or dynamic libraries. .pulpcontent archives must include files.sha256.json; every payload file must be listed and hash-matched before preview, install, or update.
The value for plugin authors is a standard expansion-pack path. Users see the target plugin, install location, and reload/rescan/restart expectation before approval, and removal deletes only the installed pack root. User-created presets remain in the plugin's normal user preset path.
Runtime plugins opt in through ContentRegistry or PresetManager. Prefer pulp_add_plugin(... CONTENT_CAPABILITIES ... CONTENT_KINDS ... CONTENT_HOT_RELOAD_KINDS ... CONTENT_MANUAL_RESCAN_KINDS ...), which generates pulp.plugin-runtime.json for agents, previews, and ValidationHarness::validate_plugin_runtime_manifest(...).
pulp_add_plugin(MySynth
...
CONTENT_CAPABILITIES content.presets.v1
CONTENT_KINDS presets
CONTENT_HOT_RELOAD_KINDS presets)
Staying in Sync¶
The cli-plugin-sync hook alerts you when the CLI C++ tables, Rust front-end
command enum, or MCP server (tools/mcp/pulp_mcp.cpp) are modified. This is a
reminder to check whether commands, skills, or hooks need matching updates.
When adding a new CLI command, consider whether it should also become a slash command or skill.