
blockbench-plugins
Blockbench plugin/extension development for the 3D modeling tool. Use when creating, modifying, or debugging JavaScript plugins for Blockbench including actions, dialogs, panels, menus, toolbars, model manipulation, animation APIs, and custom formats/codecs. Triggers on Blockbench plugin, Blockbench extension, Blockbench API, BBPlugin, model editor plugin, or 3D modeling tool extension.
- Installs
- 654
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/jasonjgardner/blockbench-mcp-project --skill blockbench-plugins- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads blockbench-plugins automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Blockbench Plugin Development
Overview
Blockbench runs on desktop and the web, exposing host APIs and bundled rendering/UI libraries to plugins. Verify the target host version and its types before choosing APIs; plugin variable isolation does not imply unrestricted native-module or filesystem access. Prefer the current generated API reference and the target checkout when older wiki examples disagree with the host. Set variant and min_version to the environments actually verified.
For model format decisions, UV units, rig distinctions and export handoffs, see format and delivery guidance. A format feature flag advertises host behavior; it does not implement missing validation or runtime serialization in a custom codec.
Quick Reference
| Task | Approach |
|---|---|
| Create clickable command | new Action() - add to menus/toolbars |
| Show form/dialog | new Dialog() with form fields |
| Add sidebar panel | new Panel() with Vue component |
| Modify model elements | Use Undo.initEdit() → modify → Undo.finishEdit() |
| Custom import/export | new Codec() + new ModelFormat() |
| React to changes | Blockbench.on('event_name', callback) |
Plugin File Structure
plugins/
└── my_plugin/
├── my_plugin.js # Main file (required, ID must match filename)
├── about.md # Extended docs (optional)
└── icon.png # 48x48 icon (optional)
Plugin Registration Template
(function() {
// Store references for cleanup
let myAction, myPanel, myDialog, eventCallback;
Plugin.register('my_plugin', {
title: 'My Plugin',
author: 'Author Name',
description: 'Short description',
icon: 'extension', // Material icon name
version: '1.0.0',
variant: 'both', // 'desktop', 'web', or 'both'
min_version: '4.8.0',
tags: ['Utility'],
onload() {
// Initialize all components here
},
onunload() {
// CRITICAL: Delete ALL components here
},
oninstall() {
Blockbench.showQuickMessage('Installed!');
}
});
})();
Actions
Actions are clickable commands for menus, toolbars, and keybindings.
myAction = new Action('my_action_id', {
name: 'Action Name',
description: 'Tooltip text',
icon: 'star',
category: 'edit', // For keybind settings
condition: () => Cube.selected.length > 0,
keybind: new Keybind({ key: 'k', ctrl: true }),
click(event) {
// Action logic
}
});
MenuBar.addAction(myAction, 'filter'); // Add to Filter menu
// Cleanup
myAction.delete();
Menu locations: 'file', 'edit', 'transform', 'filter', 'tools', 'view', 'help'
Action variants:
// Toggle (on/off state)
new Toggle('toggle_id', {
name: 'Feature',
default: false,
onChange(value) { /* handle */ }
});
// Tool (viewport interaction)
new Tool('tool_id', {
name: 'My Tool',
cursor: 'crosshair',
onCanvasClick(data) { /* handle */ },
onCanvasDrag(data) { /* handle */ }
});
Dialogs
myDialog = new Dialog({
id: 'my_dialog',
title: 'Dialog Title',
width: 540,
form: {
name: { label: 'Name', type: 'text', value: 'default' },
count: { label: 'Count', type: 'number', value: 10, min: 1, max: 100 },
enabled: { label: 'Enabled', type: 'checkbox', value: true },
mode: {
label: 'Mode',
type: 'select',
options: { a: 'Option A', b: 'Option B' },
value: 'a'
},
color: { label: 'Color', type: 'color', value: '#ff0000' },
// Conditional field
advanced: {
label: 'Advanced',
type: 'text',
condition: (form) => form.enabled
}
},
onConfirm(formData) {
console.log(formData.name, formData.count);
this.hide();
}
});
myDialog.show();
// Quick dialogs
Blockbench.textPrompt('Enter Value', 'default', (text) => { });
Blockbench.showMessageBox({ title: 'Alert', message: 'Text', buttons: ['OK'] });
Panels
Panels appear in sidebars with Vue components.
myPanel = new Panel('my_panel', {
name: 'My Panel',
icon: 'dashboard',
condition: () => Format.animation_mode,
default_position: {
slot: 'left_bar', // 'left_bar', 'right_bar', 'bottom'
height: 300
},
component: {
template: `
<div>
<h3>{{ title }}</h3>
<ul><li v-for="item in items">{{ item.name }}</li></ul>
<button @click="refresh">Refresh</button>
</div>
`,
data() {
return { title: 'Items', items: [] };
},
methods: {
refresh() {
this.items = Cube.selected.map(c => ({ name: c.name }));
}
}
}
});
// Cleanup
myPanel.delete();
Model Manipulation (with Undo)
Register persistent project edits with native Undo, including every affected aspect. Validate targets and stage asynchronous input before opening a transaction; cancel/restore it on failure. Native actions or painting APIs may own their own transaction, so do not add a competing nested one. Read-only inspection, camera movement and file writes are not equivalent to undoable model mutations. See Undo documentation.
// Start tracking
Undo.initEdit({ elements: Cube.selected });
// Modify elements
Cube.selected.forEach(cube => {
cube.from[0] += 5;
cube.to[1] = 20;
cube.rotation[1] = 45;
});
// Update view
Canvas.updateView({
elements: Cube.selected,
element_aspects: { geometry: true, transform: true }
});
// Commit
Undo.finishEdit('Move cubes');
Creating Elements
Creation must record the new objects at transaction completion, not only an empty initial list:
Undo.initEdit({ elements: [], outliner: true });
const createdCube = new Cube({ name: 'body_geo', from: [-4, 0, -2], to: [4, 12, 2] }).init();
Undo.finishEdit('Add body cube', { elements: [createdCube], outliner: true });
Canvas.updateAll();
The snippets below illustrate individual host constructors; place them inside the appropriate transaction when changing an existing project. A group's origin is a pivot; parenting does not add that origin as a translation to cube bounds.
// Cube
let cube = new Cube({
name: 'my_cube',
from: [0, 0, 0],
to: [16, 16, 16],
origin: [8, 8, 8],
rotation: [0, 45, 0]
}).init();
cube.addTo(Group.selected[0]); // Add to group
// Group (bone)
let group = new Group({
name: 'bone_arm',
origin: [0, 12, 0]
}).init();
group.addTo(); // Add to root
// Texture
let texture = new Texture({ name: 'my_texture' });
texture.fromPath('/path/to/file.png'); // or .fromDataURL()
texture.add(true); // true = add to undo
Global Collections
| Collection | Description |
|---|---|
Cube.all / Cube.selected | All cubes / selected cubes |
Group.all / Group.selected | All groups / selected groups |
Mesh.all / Mesh.selected | All meshes / selected meshes |
Texture.all / Texture.selected | All textures / selected |
Animation.all / Animation.selected | All animations / selected |
Outliner.elements | All outliner elements |
Event System
// Subscribe
eventCallback = (data) => { /* handle */ };
Blockbench.on('update_selection', eventCallback);
// Unsubscribe (use SAME function reference)
Blockbench.removeListener('update_selection', eventCallback);
Common events: update_selection, select_project, new_project, load_project, save_project, close_project, add_cube, add_group, add_texture, add_animation, select_animation, render_frame, undo, redo, finish_edit
See references/events.md for full list.
Custom Menus
let menu = new Menu([
'existing_action_id',
myAction,
'_', // Separator
{
name: 'Custom Item',
icon: 'star',
click() { /* handle */ }
},
{
name: 'Submenu',
children: [ /* more items */ ]
}
]);
menu.open(event); // Open at mouse position
Format and Codec (Import/Export)
const myCodec = new Codec('my_codec', {
name: 'My Format',
extension: 'mymodel',
compile(options) {
// Model → file content
let data = { bones: [] };
Group.all.forEach(g => {
data.bones.push({
name: g.name,
pivot: g.origin,
cubes: g.children.filter(c => c instanceof Cube).map(c => ({
from: c.from, to: c.to
}))
});
});
return JSON.stringify(data, null, 2);
},
parse(content, path) {
// File content → model
let data = JSON.parse(content);
newProject(myFormat);
data.bones.forEach(b => {
let group = new Group({ name: b.name, origin: b.pivot }).init();
b.cubes.forEach(c => {
new Cube({ from: c.from, to: c.to }).init().addTo(group);
});
});
Canvas.updateAll();
}
});
const myFormat = new ModelFormat('my_format', {
id: 'my_format',
name: 'My Format',
icon: 'icon_name',
codec: myCodec,
box_uv: true,
bone_rig: true,
animation_mode: true
});
// Cleanup
myFormat.delete();
myCodec.delete();
Condition Patterns
// Function
condition: () => Format.id === 'bedrock' && Cube.selected.length > 0
// Object (combined with AND)
condition: {
formats: ['bedrock', 'java_block'],
modes: ['edit', 'paint'],
project: true,
selected: { cube: 1 },
method: () => customCheck()
}
Code Style Conventions
| Type | Convention | Examples |
|---|---|---|
| Classes | PascalCase | OutlinerElement, Animation |
| Methods | camelCase | updateTransform, getSelectedFaces |
| Properties | snake_case | data_points, uv_offset |
| Event/Action IDs | snake_case | select_project, my_action |
Critical Cleanup Pattern
MUST delete all components in onunload() to prevent memory leaks.
let action, panel, dialog, toolbar, format, codec, eventCallback, css;
Plugin.register('my_plugin', {
onload() {
action = new Action('id', { /* ... */ });
panel = new Panel('id', { /* ... */ });
format = new ModelFormat('id', { /* ... */ });
codec = new Codec('id', { /* ... */ });
eventCallback = (data) => { };
Blockbench.on('update_selection', eventCallback);
css = Blockbench.addCSS('.my-class { color: blue; }');
},
onunload() {
action.delete();
panel.delete();
format.delete();
codec.delete();
Blockbench.removeListener('update_selection', eventCallback);
css.delete();
}
});
Anti-Patterns
// ❌ No stored reference = memory leak
onload() { new Action('leaked', { }); }
// ❌ No Undo = users can't reverse
Cube.selected.forEach(c => c.from[0] += 1);
// ❌ Bundling THREE.js (already global)
import * as THREE from 'three';
// ❌ Global pollution
window.myData = {};
Built-in Libraries (Do Not Bundle)
- THREE — Three.js 3D rendering
- Vue — host-provided reactive UI; match the host's supported component API
- JSZip — ZIP handling
- marked — Markdown parsing
- Molang — Molang expression parser
Icons
icon: 'star' // Material icon
icon: 'fa-bone' // Font Awesome
icon: 'icon-player' // Blockbench custom
icon: 'data:image/...' // Base64 image
TypeScript Setup
npm i --save-dev blockbench-types
/// <reference types="blockbench-types" />
Template Files
assets/plugin_template.js— Complete starter pluginassets/format_plugin.js— Custom format/codec example
References
- references/events.md — Event reference; confirm version-specific events in the target host
- references/api.md — Local API examples
- references/elements.md — Element types and properties
- Creating a Plugin — Official registration, lifecycle and development guidance
- Generated API reference — Current host types and comments
Verify a plugin edit with a representative project: expected data/preview, Undo then Redo, and unload/reload cleanup. For formats/codecs, check a representative export and reimport, including UV dimensions, hierarchy, names, texture references and animation behavior where supported. Passing compilation does not exercise native editor state or serialized output.
FAQ
What does the blockbench-plugins skill do?
Blockbench plugin/extension development for the 3D modeling tool. Use when creating, modifying, or debugging JavaScript plugins for Blockbench including actions, dialogs, panels, menus, toolbars, model manipulation, animation APIs, and custom formats/codecs. Triggers on Blockbench plugin, Blockbench extension, Blockbench API, BBPlugin, model editor plugin, or 3D modeling tool extension.
How do I install blockbench-plugins?
Run npx skills add https://github.com/jasonjgardner/blockbench-mcp-project --skill blockbench-plugins in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/blockbench-plugins/ (personal) or .claude/skills/blockbench-plugins/ (project).
Which AI agents can use blockbench-plugins?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is blockbench-plugins safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains blockbench-plugins?
It is published by jasonjgardner in jasonjgardner/blockbench-mcp-project. It has 654 recorded installs.
More from jasonjgardner/blockbench-mcp-project
blockbench-modeling
jasonjgardner/blockbench-mcp-project
Create and edit 3D models in Blockbench using MCP tools. Use when building geometry with cubes, creating meshes, placing spheres/cylinders, editing vertices, extruding faces, or organizing models with groups. Covers both cube-based Minecraft modeling and freeform mesh editing.
blockbench-texturing
jasonjgardner/blockbench-mcp-project
Create and paint textures in Blockbench using MCP tools. Use when creating textures, painting on models, using brush tools, filling colors, drawing shapes, applying gradients, managing texture layers, or working with UV mapping. Covers pixel art texturing, procedural painting, and UV manipulation.
blockbench-animation
jasonjgardner/blockbench-mcp-project
Create and manage animations in Blockbench using MCP tools. Use when animating 3D models, creating keyframes, managing bone rigs, editing animation curves, or working with animation timelines. Covers walk cycles, idle animations, combat animations, and complex multi-bone animations.
blockbench-mcp-overview
jasonjgardner/blockbench-mcp-project
Discover and use Blockbench MCP tools, resources, and prompts. Use for capability questions, new-project planning, mode navigation, export, display transforms, Bedrock face materials, or native armature workflows.
blockbench-use
jasonjgardner/blockbench-mcp-project
Load before Blockbench MCP calls that create, modify, or export content. Discover the active format and tools, route to modeling, UV/texturing, animation, particle, PBR, or Hytale guidance, and verify the requested result.
blockbench-pbr-materials
jasonjgardner/blockbench-mcp-project
Create and manage PBR materials in Blockbench using MCP tools. Use for Bedrock textureset.json import/export, normal or height maps, packed MER textures, material channel replacement, and uniform material properties.
Popular media & creative skills
hyperframes
heygen-com/hyperframes
Read first to make, edit, animate or render any video with HyperFrames (HTML rendered to video), including launch films, explainers, music videos, charts, maps, vertical clips, title cards, captions and overlays. Holds the render contract, the work loop and what each kind of video needs.
media-use
heygen-com/hyperframes
Get or make any media for a HyperFrames video - music, sound effects, images, icons, logos, voiceover, avatar and generated video, transcripts, cutouts, colour grades and looks - with HeyGen or free local tools, and mix placed audio. Also for footage that looks dark, flat or dull, or should be stylized or hidden.
hyperframes-registry
heygen-com/hyperframes
About 450 ready-made HyperFrames blocks and components installed as editable source - transitions, overlays, titles, kinetic type, captions, charts, map overlays, 3D, camera moves. Use it before hand-building any named visual (CRT scanlines, glitch, film grain, a chart); also for hyperframes add and catalog.
hyperframes-creative
heygen-com/hyperframes
Non-animation creative direction for HyperFrames videos. Use for design spec (frame.md / design.md) handling, palettes, typography, narration, beat planning, audio-reactive visuals, composition patterns, and brand / style decisions. For atomic motion patterns and scene blueprints, use hyperframes-animation.
ai-video-generation
101-skills/superpowers
Generate AI videos with Google Veo, Seedance 2.0, HappyHorse, Wan, Grok and 40+ models via inference.sh CLI. Models: Veo 3.1, Veo 3, Seedance 2.0, HappyHorse 1.0, Wan 2.5, Grok Imagine Video, OmniHuman, Fabric, HunyuanVideo. Capabilities: text-to-video, image-to-video, reference-to-video, video editing, lipsync, avatar animation, video upscaling, foley sound. Use for: social media videos, marketing content, explainer videos, product demos, AI avatars. Triggers: video generation, ai video, text to video, image to video, veo, animate image, video from image, ai animation, video generator, generate video, t2v, i2v, ai video maker, create video with ai, runway alternative, pika alternative, sora alternative, kling alternative, seedance, happyhorse
ai-image-generation
101-skills/superpowers
Generate AI images with GPT-Image-2, FLUX, Gemini, Grok, Seedream, Reve and 50+ models via inference.sh CLI. Models: GPT-Image-2, FLUX Dev LoRA, FLUX.2 Klein LoRA, Gemini 3 Pro Image, Grok Imagine, Seedream 4.5, Reve, ImagineArt. Capabilities: text-to-image, image-to-image, inpainting, LoRA, image editing, upscaling, text rendering. Use for: AI art, product mockups, concept art, social media graphics, marketing visuals, illustrations. Triggers: flux, image generation, ai image, text to image, stable diffusion, generate image, ai art, midjourney alternative, dall-e alternative, text2img, t2i, image generator, ai picture, create image with ai, generative ai, ai illustration, grok image, gemini image, gpt image, openai image, chatgpt image