From pai-pro
Designs semantic node groups on a filmmaking canvas — for scenes, character references, and act beats. Use when nodes share meaning and would read clearer with a titled frame.
How this skill is triggered — by the user, by Claude, or both
Slash command
/pai-pro:groups-composeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A good grouping earns its frame. Rule of thumb:
A good grouping earns its frame. Rule of thumb:
If fewer than 3 members resolve, or the tie is just "these happened to be generated in a row", skip the group. A too-eager grouping is worse than none — it adds a frame the reader has to parse without carrying real meaning.
id, title, node_ids (and optionally hue 0–360).x / y / width / height / any "collapsed" flag.id format: ^group_[a-z0-9_]+$. Titles are free-form (≤ 30 chars recommended).Pick the one that fits. When unsure, read ./workflow.json first to see which ids actually exist.
Most common. Group the prompt, generated imagery, and any notes that all belong to the same scripted scene.
Scene <N> — <location or beat>. Examples:
Scene 1 — CausewayScene 3 — Kitchen, 2 AMScene 5 — Rooftop chaseA character card + its reference images.
<Character name> — references. Examples:
Morris — referencesRiya — referencesimage_result nodes depicting the same character.Coarser than scene — groups a whole Act or story beat.
Act <N> or a beat name. Examples:
Act 1Opening titlesChase sequenceLess common; use only when the user explicitly sorts by quality / status.
Approved, In progress, Rejected.Groups go through the canvas mutator — the agent does NOT Write /
Edit workflow.json directly (a PreToolUse hook blocks that path).
read ./workflow.json to enumerate existing node ids + existing groups (reads are unrestricted; only writes are blocked).nodes AND aren't already in another group (the mutator rejects double-membership with klass:conflict).addGroup:
node "$PAI_REPO_ROOT/server/scripts/canvas_mutate.js" \
--op addGroup \
--payload-json '{"group":{"title":"Scene 1 — Causeway","node_ids":["image_3","video_1","note_2"],"hue":200}}'
Stdout returns assigned.group_id. The CLI auto-mints group_<N> if you don't pass an explicit id in the payload.updateGroup, passing the full new node_ids list (the mutator replaces the list wholesale and dedupes):
node "$PAI_REPO_ROOT/server/scripts/canvas_mutate.js" \
--op updateGroup \
--payload-json '{"id":"group_3","patch":{"node_ids":["image_3","video_1","note_2","image_5"]}}'
x / y / width / height into a group or its members. The system computes all geometry from the node_ids list.node_ids).Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub utopai-research/pai-pro --plugin pai-pro