skills/superplane-canvas-builder/SKILL.md
Design and build SuperPlane workflow canvases from requirements. Translates workflow descriptions into canvas YAML with triggers, actions, edges, and expressions. Use when the user wants to create a new workflow, build a canvas, design a pipeline, or wire up actions. Triggers on "build canvas", "create workflow", "design pipeline", "automate".
npx skillsauth add superplanehq/skills superplane-canvas-builderInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Translate workflow requirements into SuperPlane canvas YAML.
| Task | Command |
| --- | --- |
| List actions | superplane index actions |
| Actions from integration | superplane index actions --from <integration> |
| Describe an action | superplane index actions --name <name> |
| List triggers | superplane index triggers --from <integration> |
| Generate starter YAML | superplane canvases init |
| Create canvas | superplane canvases create --file canvas.yaml |
| Update canvas | superplane canvases update <name-or-id> --draft -f canvas.yaml |
Always follow this sequence. The CLI is the primary path — it gives exact names, IDs, and schemas that documentation cannot reliably substitute.
command -v superplane
If this does not print a path: stop. Tell the user to install the CLI from https://docs.superplane.com/installation/cli and re-run the task. Do not attempt to install it on their behalf. Do not silently fall back to doc-based design.
Then verify the current session:
superplane whoami
If whoami fails because of authentication, DNS, timeout, or connection issues, the CLI is installed but the session is not usable yet. Ask the user to connect, fix the context, or allow network access as needed. Do not continue without a working CLI session.
If not yet connected:
superplane connect <URL> <TOKEN>
superplane whoami
If connection details are not available, stop and ask the user to connect/provide the required URL and token. Do not continue without a working CLI session.
Versioning is always on in this environment. Skip mode detection and use --draft on every superplane canvases update command.
superplane canvases update <name-or-id> --draft --file canvas.yaml
Before running discovery commands, identify what the workflow needs:
Collect the list of required providers from this analysis — you will check them in the next step.
Run superplane integrations list to get all connected integrations in the org. Compare against the required providers from step 2.
If any required provider is missing: stop and tell the user before writing any YAML. Example:
This canvas needs GitHub and Daytona integrations. Your org has GitHub connected but Daytona is not connected. Please connect it in the SuperPlane UI (Settings → Integrations) before proceeding.
Do not generate YAML that references providers the org has not connected — it will fail with "integration is required" on every affected node.
Once all providers are confirmed connected, discover exact names and schemas:
superplane integrations list # connected instances → real integration IDs
superplane index triggers --from <provider> # exact trigger names
superplane index actions --from <provider> # exact action names
Inspect required config fields, output channels, and payload shape:
superplane index triggers --name github.onPush --output json
superplane index actions --name semaphore.runWorkflow --output json
List runtime options for integration-resource fields:
superplane integrations list-resources --id <id> --type <type>
Hard gate before writing/applying YAML: for every integration-resource field value you set (for example: repository, snapshot, sandbox, project), verify the exact value exists in list-resources output for that integration. If it does not exist, stop and ask the user which valid value to use.
Schema precedence rule: if provider reference examples conflict with CLI schema output (superplane index ... --output json) or current list-resources values, follow CLI output. References are helper material; CLI is source of truth.
Use the exact trigger and action names from step 3 — not guesses from documentation.
true/false, Approval → approved/rejected)default when the expression is true; false events stop silentlySee Components & Triggers Reference for the full list.
Every node needs a position: { x, y }. Nodes are 515px wide × 215px tall — use these spacing rules to prevent overlap:
| Direction | Increment | Why | | --- | --- | --- | | Horizontal (x) | +600px per column | 515 width + 85 gap | | Vertical (y) | +300px per row | 215 height + 85 gap |
Start the first node (trigger) at { x: 120, y: 100 }.
Linear pipeline — same y, increment x:
Trigger: { x: 120, y: 100 } → Step A: { x: 720, y: 100 } → Step B: { x: 1320, y: 100 }
Branching — branches share the same x column, spread on y. Center the source node vertically relative to its branches:
┌─ Branch A: { x: 1320, y: 100 }
Source: { x: 720, y: 250 } ───┤
└─ Branch B: { x: 1320, y: 400 }
Fan-in (Merge) — next x column after branches, y centered between them:
Branch A: { x: 1320, y: 100 } ──┐
├── Merge: { x: 1920, y: 250 }
Branch B: { x: 1320, y: 400 } ──┘
For 3+ branches, keep adding 300 to y for each branch and center the source/merge accordingly.
STOP before writing any expression that references payload fields you have not confirmed. Do not guess field paths from trigger or action names.
Every node output is wrapped in an envelope: { data: {...}, timestamp, type }. All three access patterns return this envelope, so you always need .data. to reach the actual payload:
| Pattern | Description |
| --- | --- |
| $['Node Name'].data.field | Access any upstream node's output by name |
| root().data.field | Access the root event that started the run |
| previous().data.field | Access the immediate upstream node's output |
Common mistake: writing
$['Create Sandbox'].idinstead of$['Create Sandbox'].data.id. Always include.data..
Important — example payloads already represent the envelope. The example payload printed by
superplane index triggers --name <trigger>(and shown in this skill's reference files) is the full envelope: the outermost{ data: {...}, timestamp, type }.root().datareturns that top-leveldataobject — do not add an extra.dataon top of it. To build a correct expression, count thedatakeys directly from the example JSON: one.dataper nesteddatakey you need to traverse, no more.Nested
datakeys. Some webhooks (notably Sentry) carry their owndatafield inside the payload body. The correct path therefore has two.datasegments —root().data.data.issue.title— not three.root().dataalready unwraps the envelope; the second.datawalks into the webhook's owndatafield. If you find yourself writingroot().data.data.data.…, you are double-counting the envelope.
Use double curly braces {{ }} for expressions in configuration fields:
{{ $['GitHub onPush'].data.ref }}
Check these sources in order — use the first one available:
Existing executions — inspect real payloads from prior runs (most reliable):
superplane executions list --canvas-id <id> --node-id <nid> -o yaml
Provider reference files in this skill — check the references/ directory for the provider you are using. These contain payload examples and known gotchas.
SuperPlane docs — fetch the provider's action page from the LLM-friendly docs:
After the first real execution, always go back to source 1 to verify and correct expressions. The trigger name does not map 1:1 to payload structure — always check the provider reference file or docs for the actual webhook event a trigger maps to.
When an action executes shell commands (e.g., daytona.executeCommand, ssh):
workingDirectory / envVars config instead of inline cd or export in the shell string. This reduces quoting complexity and failure surface.STEP_OK / STEP_FAILED). Large or binary stdout can cause node processing issues.references/ directory) for the shell execution model, hardened command templates, and known failure patterns specific to that integration.command: |-) over folded single-line strings to avoid whitespace/newline parse artifacts in bash -lc.outputs in execution YAML to confirm expected channel routing (success vs failed) matches your edge wiring.Generate a starter YAML if starting from scratch:
superplane canvases init --output-file canvas.yaml
# or start from a template:
superplane canvases init --template health-check-monitor --output-file canvas.yaml
Then create from the file or update an existing canvas:
superplane canvases create --file canvas.yaml
# or update an existing canvas:
superplane canvases update <name-or-id> --draft --file canvas.yaml
When creating a new canvas from YAML, create --file already applies the graph in the file:
superplane canvases create --file canvas.yaml
Workflow rules:
superplane canvases create --file canvas.yaml accepts the resource-style Canvas YAML from the spec (apiVersion, kind, metadata, spec).superplane canvases update ... after create when you are intentionally applying additional changes, such as a later file that includes metadata.id, or explicit auto-layout flags different from the defaults used by create.superplane canvases update ... command should include --draft.Then verify:
superplane canvases get <name>
Check for errorMessage or warningMessage on any node.
Before calling the canvas "ready", confirm all of the following:
superplane integrations listintegration-resource value verified via superplane integrations list-resourcessuperplane canvases get <name> -o yaml shows empty errorMessage and warningMessage on all nodesoutputs from critical branching nodesnodes:
- { id: trigger, ..., position: { x: 120, y: 100 } }
- { id: a, ..., position: { x: 720, y: 100 } }
- { id: b, ..., position: { x: 1320, y: 100 } }
- { id: c, ..., position: { x: 1920, y: 100 } }
edges:
- { sourceId: trigger, targetId: a, channel: default }
- { sourceId: a, targetId: b, channel: default }
- { sourceId: b, targetId: c, channel: default }
nodes:
- { id: trigger, ..., position: { x: 120, y: 250 } }
- { id: check, ..., action: { name: if }, position: { x: 720, y: 250 } }
- { id: on-true, ..., position: { x: 1320, y: 100 } }
- { id: on-false, ..., position: { x: 1320, y: 400 } }
edges:
- { sourceId: trigger, targetId: check, channel: default }
- { sourceId: check, targetId: on-true, channel: true }
- { sourceId: check, targetId: on-false, channel: false }
Filter only emits to default when true. False events stop — no edge needed.
nodes:
- { id: trigger, ..., position: { x: 120, y: 100 } }
- { id: filter, ..., action: { name: filter }, position: { x: 720, y: 100 } }
- { id: next-step, ..., position: { x: 1320, y: 100 } }
edges:
- { sourceId: trigger, targetId: filter, channel: default }
- { sourceId: filter, targetId: next-step, channel: default }
nodes:
- { id: trigger, ..., position: { x: 120, y: 250 } }
- { id: a, ..., position: { x: 720, y: 100 } }
- { id: b, ..., position: { x: 720, y: 400 } }
- { id: merge, ..., position: { x: 1320, y: 250 } }
- { id: final, ..., position: { x: 1920, y: 250 } }
edges:
- { sourceId: trigger, targetId: a, channel: default }
- { sourceId: trigger, targetId: b, channel: default }
- { sourceId: a, targetId: merge, channel: default }
- { sourceId: b, targetId: merge, channel: default }
- { sourceId: merge, targetId: final, channel: default }
nodes:
- { id: ci-done, ..., position: { x: 120, y: 100 } }
- { id: timegate, ..., position: { x: 720, y: 100 } }
- { id: approval, ..., position: { x: 1320, y: 100 } }
- { id: deploy, ..., position: { x: 1920, y: 100 } }
edges:
- { sourceId: ci-done, targetId: timegate, channel: default }
- { sourceId: timegate, targetId: approval, channel: default }
- { sourceId: approval, targetId: deploy, channel: approved }
| Need | Use Skill | | --- | --- | | CLI commands and authentication | superplane-cli | | Debug a failed run | superplane-monitor |
For agents that can fetch URLs, the full SuperPlane docs are available in LLM-friendly format:
data.data gotchadevelopment
Design and build SuperPlane workflow apps from requirements. Translates workflow descriptions into app canvas YAML with triggers, actions, edges, and expressions. Use when the user wants to create a new workflow app, build a canvas, design a pipeline, or wire up actions. Triggers on "build app", "build canvas", "create workflow", "design pipeline", "automate".
development
Monitor and debug SuperPlane workflow executions. Inspect runs, diagnose failures, and manage execution queues. Use when a workflow fails, an execution is stuck, or the user wants to check run status. Triggers on "debug", "failed", "failure", "execution", "output channel", "passed but failed", "run status", "stuck", "queue", "troubleshoot".
tools
Use when working with the SuperPlane CLI to discover integrations, actions, and triggers, build or troubleshoot apps and canvases, manage secrets, and monitor executions. Covers authentication, list/get commands, interpreting configuration schemas, wiring channels between nodes, resolving integration binding issues, and inspecting runs. Triggers on "superplane", "app", "canvas", "workflow", "CLI", "connect", "integration is required", "execution".
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.