From seldonframe
Scaffolds a real SeldonFrame block skeleton (BLOCK.md, tools.ts, subscription stubs, test stubs) from natural-language intent. Builder owns git review and workspace install.
How this skill is triggered — by the user, by Claude, or both
Slash command
/seldonframe:block-creationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Invoke this skill when the builder expresses intent to create a new
Invoke this skill when the builder expresses intent to create a new block. Trigger phrases include:
Do NOT invoke when the builder is asking to:
install_* tools).The scaffold writes files to the builder's repo working tree. It does NOT:
Those are the builder's follow-up actions (git add / git commit /
git push, then install_block against a workspace). Claude Code
is a code-gen assistant here, not a platform admin.
Claude Code reads the builder's natural-language intent and
constructs a BlockSpec JSON object matching the shape below.
Before constructing the spec, Claude should Read:
packages/crm/src/blocks/notes.block.md (simple tool-only
block — the PR 1 C7 smoke-test)packages/crm/src/blocks/crm.block.md (real-world anatomy
with ## Subscriptions declaring a reactive handler)packages/crm/src/lib/scaffolding/nl/example-specs.ts —
EXAMPLE_SPECS export. Two examples: tool-only (contact-notes)
packages/crm/src/lib/scaffolding/spec.ts — BlockSpecSchema
Reading order: anatomies first → schema → examples. Each reads in under 30 seconds; together they give Claude the concrete pattern needed to translate NL confidently.
Required fields:
slug: kebab-case lowercase, e.g. "notes", "client-satisfaction". Cannot collide with reserved core blocks: crm, caldiy-booking, email, sms, payments, formbricks-intake, landing-pages.title: human-readable title, e.g. "Notes", "Client Satisfaction".description: one-line builder-facing description.triggerPhrases: 2-5 natural-language phrases that would activate this block.frameworks: array of framework strings, e.g. ["universal"].Optional fields (defaulted if absent):
produces: array of { name, fields } event declarations.consumes: array of { kind, ... } discriminated-union entries (kind: "event" | "soul_field" | "trigger_payload").tools: array of tool definitions: { name, description, args: [...], returns: [...], emits: [...] }.subscriptions: array of { event, handlerName, description, idempotencyKey } reactive handlers. event is fully-qualified: "<source-block>:<event.name>".Before translating NL → BlockSpec, call the deterministic classifier once to sanity-check the intent:
import { classifyIntent } from "@/lib/scaffolding/nl/intent-classifier";
const classification = classifyIntent(nlIntent);
// { tier: 1 | 2 | 3, issues: string[], suggestedAction: string }
Behavior by tier:
suggestedAction points at what to ask). Wait for a reply.
Re-classify after the reply; proceed only when classification
is no longer tier 1.TODO (scaffold-default) comments the builder
can grep post-scaffold.The classifier's heuristics are loose — false-negative tier-2 intents are acceptable (downstream BlockSpec validation catches structural problems). False-positive tier-3 decisions are preferred over false-negative — better to refuse once and require confirmation than scaffold a destructive tool silently.
create_<entity> /
list_<entity>s / get_<entity> as defaults. Every scaffolded
default lands with TODO (scaffold-default) markers the builder
can grep.Once the BlockSpec is constructed, write it to a temporary file and invoke the scaffold CLI:
# Claude writes /tmp/spec.json with the BlockSpec JSON
pnpm scaffold:block --spec /tmp/spec.json
The scaffold will:
packages/crm/src/blocks/<slug>.* and packages/crm/tests/unit/blocks/<slug>.spec.ts.parseBlockMd round-trip on the new BLOCK.mdtsc --noEmit across the CRM packagepnpm emit:blocks:check (after the builder adds the block to the emit TARGETS registry on next step)git clean recovery commands.After the scaffold succeeds, tell the builder:
scripts/emit-block-tools.impl.ts TARGETS list so emit:blocks:check covers it.pnpm emit:blocks to populate the TOOLS block in the BLOCK.md.pnpm test:unit — new test stubs appear as todos.git diff / git add / git commit when satisfied.On failure, relay the orphan report verbatim so the builder has the exact recovery commands.
{
"slug": "notes",
"title": "Notes",
"description": "Simple note-taking on contacts.",
"triggerPhrases": [
"Add a notes block",
"Install notes",
"Let me jot notes on contacts"
],
"frameworks": ["universal"],
"produces": [
{
"name": "note.created",
"fields": [
{ "name": "noteId", "type": "string", "nullable": false },
{ "name": "contactId", "type": "string", "nullable": false }
]
}
],
"consumes": [],
"tools": [
{
"name": "create_note",
"description": "Create a note on a contact.",
"args": [
{ "name": "contactId", "type": "string", "nullable": false, "required": true },
{ "name": "body", "type": "string", "nullable": false, "required": true }
],
"returns": [
{ "name": "noteId", "type": "string", "nullable": false, "required": true }
],
"emits": ["note.created"]
}
],
"subscriptions": []
}
Pass --dry-run to see what would be created without writing:
pnpm scaffold:block --spec /tmp/spec.json --dry-run
Useful for previewing before committing to the scaffold.
If the scaffold fails mid-pipeline:
git clean
commands to remove them.npx claudepluginhub seldonframe/seldonframeControls SeldonFrame directly from Claude Code to create, customize, and manage client workspaces, blocks, and templates with live previews and one-command deployment.
Scaffolds ACF Composer blocks with custom element architecture, scoped CSS, theme variations, and JS lifecycle. Use when creating new Gutenberg blocks in Sage-based WordPress themes.
Scaffolds greenfield project architecture and AI agent harness via interview-driven decisions. Outputs markdown spec with code structure exemplar, tests, guardrails, CLAUDE.md setup, and unified plan. Invoke via /scaffold for new projects.