Guizang Social Cards
op7418/guizang-social-card-skill
Produces social card sets for Xiaohongshu and WeChat: carousels, Live Photo motion cards and puzzle layouts, and WeChat cover pairs, rendered from single-file HTML.
Stage the frame on a NodeTool timeline — grids, focal placement, safe areas per aspect ratio, depth layers and parallax, camera moves, and where elements enter and leave.
$ npx skills add nodetool-ai/nodetool --skill frame-composition -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install nodetool-ai/nodetool frame-composition --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/nodetool-ai/nodetool.git skills-src && mkdir -p .claude/skills && cp -r skills-src/packages/system-skills/frame-composition .claude/skills/frame-composition && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "frame-composition" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/frame-composition into .claude/skills/frame-composition/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "frame-composition", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/frame-compositionType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add nodetool-ai/nodetool --skill frame-composition -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install nodetool-ai/nodetool frame-composition --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nodetool-ai/nodetool.git skills-src && mkdir -p .agents/skills && cp -r skills-src/packages/system-skills/frame-composition .agents/skills/frame-composition && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "frame-composition" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/frame-composition into .agents/skills/frame-composition/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "frame-composition", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add nodetool-ai/nodetool --skill frame-composition -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install nodetool-ai/nodetool frame-composition --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nodetool-ai/nodetool.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/packages/system-skills/frame-composition .cursor/skills/frame-composition && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "frame-composition" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/frame-composition into .cursor/skills/frame-composition/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "frame-composition", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/nodetool-ai/nodetool.git --path packages/system-skills/frame-composition--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add nodetool-ai/nodetool --skill frame-composition -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install nodetool-ai/nodetool frame-composition --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nodetool-ai/nodetool.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/packages/system-skills/frame-composition .gemini/skills/frame-composition && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "frame-composition" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/frame-composition into .gemini/skills/frame-composition/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "frame-composition", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install nodetool-ai/nodetool frame-compositionInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add nodetool-ai/nodetool --skill frame-composition -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/nodetool-ai/nodetool.git skills-src && mkdir -p .github/skills && cp -r skills-src/packages/system-skills/frame-composition .github/skills/frame-composition && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "frame-composition" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/frame-composition into .github/skills/frame-composition/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "frame-composition", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add nodetool-ai/nodetool --skill frame-composition -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install nodetool-ai/nodetool frame-composition --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nodetool-ai/nodetool.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/packages/system-skills/frame-composition .opencode/skills/frame-composition && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "frame-composition" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/frame-composition into .opencode/skills/frame-composition/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "frame-composition", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
frame-compositionStage the frame on a NodeTool timeline — grids, focal placement, safe areas per aspect ratio, depth layers and parallax, camera moves, and where elements enter and leave.
Frame Composition is an agent skill from nodetool-ai/nodetool. Stage the frame on a NodeTool timeline — grids, focal placement, safe areas per aspect ratio, depth layers and parallax, camera moves, and where elements enter and leave. Use when placing titles, lower thirds, shapes or overlays, when a layout must survive 16:9 and 9:16, when adding a push or a parallax move, or when a frame reads flat or cramped. Not for what a clip says or when it cuts.
Its SKILL.md is about 3.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Media & Creative. The repository describes itself as: Agent-first Creative Workspace. The licence is AGPL-3.0.
Read from SKILL.md and the folder at commit 58765d3. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are javascript and json).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Frame Composition loads about 3.5k tokens when it runs. Until then it costs about 102 tokens; SKILL.md has 1,920 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from nodetool-ai/nodetool at commit 58765d3, republished under its AGPL-3.0 licence (© nodetool-ai). 1,920 words, ~3,505 tokens.
.claude/skills/frame-composition/SKILL.md (or your agent's skills folder).Where things sit, how deep the frame is, and how the camera moves through it.
motion-graphics is the build loop; timeline-edit-ops carries the op
contract. This decides the coordinates you pass either.
| What | Space | Read as |
|---|---|---|
shapeStyle.x/y/width/height, x2/y2, d | 0..1 of the frame | 0.5 is the frame's middle |
set_mask x/y/width/height, d | 0..1 of the layer | 0.5 is the clip's own middle, not the frame's |
positionX / positionY curves | canvas px | Absolute, and folds as replace |
offsetX / offsetY curves | canvas px, added | Composes with everything else |
slide distance, kenBurns driftX/driftY | fraction of frame width or height | 0.3 travels 30% of the frame |
anchorX / anchorY | 0..1 | The point a scale or a rotation pivots on |
textStyle.fontSizePx | sequence px | Against height from get_timeline, not the preview width |
transform.depthPx, camera2d.position/depthPx/focalLengthPx | sequence px | Perspective; clip depth also orders clips within one track |
layout.gap, layout.padding | sequence px | Flex container spacing, measured against its children's rendered boxes |
Read width, height and fps off get_timeline before you compute anything.
A layout authored against 1920×1080 and saved onto a 1080×1920 sequence is off
by more than a crop.
Building with @nodetool-ai/sandbox-timeline (see motion-graphics for when
code is the right surface)? A container decides where its children sit —
you almost never write x/y for text. s.stack(children, o) and
s.row(children, o) build a real Yoga flex container and reparent
children onto it as its real children — nest freely, a row of stacks
or a stack holding a nested row both resolve correctly. A text child
reflows to whatever width Yoga offers it, not a guessed line length.
The container's own placement in the frame is o.at ({x, y}, default the
frame centre) plus o.anchor (default "center"): anchor names the point
of the container's own computed box that lands at at — the name
"left" puts that box's left edge at at.x, no measuring a sibling's width
required. Named anchors: "top-left", "top", "top-right", "left",
"center", "right", "bottom-left", "bottom", "bottom-right", or pass
{x, y} fractions directly. o.align (cross axis, default "start") and
o.justify (main axis, unset) are the Yoga alignItems/justifyContent.
A child's own flex sizing is o.flexItem on that child's own call (grow,
width, alignSelf, …); absolute: true on a rect/ellipse (or any
clip) takes it out of flow and resizes it to fill its flex parent's box
exactly — how a plate sits behind a card's text with no pixel math.
Reach for explicit x/y only for decoration (a stray mark, a background
shape) or a deliberate free placement that has nothing to do with reading
order. Anything a viewer reads — a title, a kicker, a caption, a row of
stats — goes in a container.
Title block — kicker, title, sub, stacked with a shared rhythm:
// fragment
const kicker = s.kicker("LAUNCHING TODAY");
const title = s.text("Round-ups", { size: 120, weight: 700 });
const sub = s.text("on every card", { size: 40 });
s.stack([kicker, title, sub], { gap: 20 });Lockup — a mark beside its wordmark, one row:
// fragment
const mark = s.image(logoAssetId);
const wordmark = s.text("Northwind", { size: 64, weight: 700 });
s.row([mark, wordmark], { gap: 16, align: "center" });Card — a padded column over an absolute plate:
// fragment
const plate = s.rect(1, 1, "#0c2a21", { r: 24, absolute: true });
const heading = s.text("Plan Pro", { size: 48, weight: 700 });
const price = s.text("$12/mo", { size: 32 });
s.stack([plate, heading, price], { gap: 8, padding: 24 });List / grid — a row that wraps into a grid when it runs out of width:
// fragment
const chips = ["Round-ups", "Instant transfers", "No fees"].map((t) => s.pill(t));
s.row(chips, { gap: 12, wrap: true });Twelve columns for landscape, six for vertical. For a 1920-wide frame with a 100px outer margin and a 24px gutter:
content = 1920 − 2×100 = 1720
column = (1720 − 11×24) / 12 = 121.3pxSpace everything in multiples of 8. fontSizePx for body copy sits near 2.5–4%
of frame height; below 2.5% validate_timeline reports text_illegible.
Choose the family, weights, and title scale from motion-direction § Typography
before placing text on this grid.
Place the subject on a thirds power point, not dead centre, unless the piece uses symmetry deliberately. The intersections:
| Sequence | Power points (px) |
|---|---|
| 1920×1080 | x 640 / 1280, y 360 / 720 |
| 1080×1920 | x 360 / 720, y 640 / 1280 |
| 1080×1080 | x 360 / 720, y 360 / 720 |
Rank the eye's path by size, then contrast, then colour, then position. One primary per frame; everything else supports. Leave negative space around it — a frame filled edge to edge reads as cheap and gives the motion nowhere to go.
Split the picture into background, midground and foreground. Track index
controls order between tracks: lowest index draws on top. Within one
track, clips sort by transform.depthPx: farther values draw first and
nearer, positive values draw later, in front. The same depth controls
perspective under the sequence's camera2d. Moving a clip to another track
changes its overlap order but not its camera distance.
| Plane | Suggested track index | Clip depth | Motion and look |
|---|---|---|---|
| Foreground | lowest | Nearer, positive | The move the eye follows; sharp unless focus shifts |
| Midground | middle | Around zero | The subject and contrast peak |
| Background | highest | Farther, negative | Small drift and lower contrast |
For flat parallax, run three speeds over one window. One kenBurns per layer
with zoom: 0 and a different drift is a fullClip preset, so all three
cover the same span:
{"role": "loop", "preset": "kenBurns",
"params": {"zoom": 0, "driftX": -0.02, "driftY": 0}}Background −0.02, midground −0.06, foreground −0.12. One layer at one speed is not parallax, it is the template moving.
For a shared 2.5D move, give the layers distinct transform.depthPx values and
keyframe the sequence's camera2d. Its absolute timeMs keyframes interpolate
camera position and depth linearly. focusDepthPx and aperturePx control depth of
field. Use one camera move to connect the planes, then inspect a middle frame
for unwanted scale or blur. Set track indexes for overlap between tracks and
clip depth for order within a track.
For a tilted card wall, parent the cards to a group with the wall's 2D
rotation, rotationX, and perspective. Give each card its own depthPx
and scroll curve, then use camera2d for the shared push and depth blur.
This is a flat card projection: preview the wall at several frames to check
that spacing, overlap, and blur read as one assembly.
For a move with a shape of its own, write a custom curve instead and mind the
role: an in window holds its t=0 values before it and contributes nothing
after, an out window holds its t=1 values after it, and a loop repeats its
cycle — so a one-way travel that must stay where it landed is an out, and a
loop curve has to return to the value it started on or it jumps every cycle.
Parent the assembly to a group when the layers must hold their relationship
through a move: add_group, then animate the group. Children keep their own
tracks, so grouping never changes what covers what.
For a transition on the assembled picture, set transitionIn on the group. The
children stay parented on their own tracks while the transition acts once on
their precomposed surface.
Shape geometry is rasterized inside a frame-sized source surface before the
clip is placed. Keep normalized shapeStyle geometry inside that surface,
then move the clip or parent group with transform.position or custom
offsetX/offsetY curves for scrolling walls and flying cards. Geometry
authored outside the source surface clips before placement.
Choose between a sequence camera move and a local clip move. camera2d
keyframes move the view across all depth planes. A layer animation moves one
clip, and its anchor decides where scale or rotation pivots.
| Move | How | Timing |
|---|---|---|
| Push / pull | kenBurns with zoom 0.08–0.2 and direction in or out | 1500–4000ms, easeInOut |
| Drift | kenBurns driftX / driftY, ±0.02–0.08 | Same window as the zoom |
| Pan | custom curve on offsetX across the clip | 800–2000ms, easeInOut |
| Whip | offsetX over 150–250ms with a blur effect at 12–24px | On a cut, never mid-shot |
| Follow | offsetX and offsetY tracking the subject, subject held off-centre and leading | Whatever the action takes |
camera2d is a document field. set_clip_params changes a clip's transform
but refuses camera2d, layout, repeater, motionBlur, and other new document
fields. Read the full document with get_timeline, change the relevant fields,
then write the full document with set_timeline_document. Keep its tracks,
clips, markers, tempo, setup, media tracks, template identity, and other fields
in the write. timeline-edit-ops carries the
op contract.
kenBurns is fullClip: it ignores durationMs and delayMs and runs across
the whole clip. To time a push to something shorter, write it as a custom
scale curve instead.
One move per beat. A push plus a pan plus a rotate reads as chaos, and the three fold together into a direction nobody chose.
Motion that follows reading direction feels natural; reversing it reads as going
back. Match slide's direction to intent — it names the edge the element
arrives from:
pop, or a scale curve rather than a travel.Enter and leave through the nearest edge. Keep distance at or below 0.35 or
the travel reads as a slide of the whole template — pair a longer move with a
scale or opacity change on the same window. Same vocabulary on the cut:
set_transition direction on wipe, push and slide also names the edge
the incoming clip arrives from.
Keep titles, logos, faces and calls to action inside the margin. The numbers are
fractions of the frame, so convert against width and height.
| Aspect | Top | Bottom | Sides |
|---|---|---|---|
| 16:9 | 5% | 5% | 5% |
| 9:16 | 12–14% | 18–20% | 6% |
| 1:1 | 7% | 7% | 7% |
| 4:5 | 8% | 8% | 6% |
On 1080×1920 that leaves the usable band roughly y 250 to y 1570. A caption clip
already sits at bottomMarginFrac 0.12 by default, which is inside the phone UI
zone on some platforms — raise it rather than assuming.
Master in the widest target with the focal point inside the centre band, then
restack for vertical: move the headline above the subject, pull the subject
up out of the bottom UI zone, and raise fontSizePx by about 20%. Cropping a
16:9 layout to 9:16 clips whatever sat in the outer columns, which is usually the
logo and the call to action.
Building in code, restacking is usually one option change on the container
above — flip s.row to s.stack (or its align/justify), or move it to a
new at/anchor — not a rebuild of every child's x/y.
On the ops path, layout: {display: "flex", flexDirection: "row" | "column", gap} on a group clip keeps its real children (their parentId names the
group) laid out with ordinary CSS flexbox — justifyContent/alignItems
position them, padding insets the container. For a shape behind text, give
the shape flexItem: {position: "absolute", inset: 0} inside a padded flex
column holding the text: the shape's box resizes to the text's padded box,
including an animated font size, with no manual pixel math. These relations
avoid redoing pixel math for each text change. A 16:9 document still needs a
separate placement pass for 9:16, with safe areas checked at that size.
preview_timeline_frame composites the real picture — every track in order,
transforms and opacity applied, animations mid-flight. Read the layer list it
returns beside each frame: it names the stack top first with each layer's
z_index, opacity and wipe progress, which answers most staging questions
without looking at a pixel.
Preview at the midpoint of every move, not at its ends. What frames catch and a validator cannot: a title that slid outside the frame, a scrim covering the face it was meant to sit beside, a lower third under the wrong element because two track indexes are the wrong way round, a layer that never draws because it is on an audio track.
distance ≤ 0.35 or paired with a second
channel.© nodetool-ai, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in packages/system-skills/frame-composition of nodetool-ai/nodetool.
Open the folder on GitHubat commit 58765d3
Frame Composition next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Frame Composition this skillnodetool-ai/nodetool | 560 | — | ~3.5k | Automated safety check: Pass | AGPL-3.0 | |
| Guizang Social Cardsop7418/guizang-social-card-skill | 7.4k | 1 repos | ~7.8k | Automated safety check: Pass | AGPL-3.0 | |
| Weekly Changelog Videoheygen-com/hyperframes | 59k | — | ~3.3k | Automated safety check: Pass | Apache-2.0 | |
| Anthropic Brand Stylinganthropics/skills | 180k | 30 repos | ~559 | Automated safety check: Pass | Apache-2.0 | |
| MoneyPrinterTurbo Video Generatorharry0703/MoneyPrinterTurbo | 129k | — | ~2.1k | Automated safety check: Warn | MIT | |
| Brag Slim Launch Video Makerlatent-spaces/brag | 14k | 1 repos | ~1.9k | Automated safety check: Pass | MIT |
op7418/guizang-social-card-skill
Produces social card sets for Xiaohongshu and WeChat: carousels, Live Photo motion cards and puzzle layouts, and WeChat cover pairs, rendered from single-file HTML.
heygen-com/hyperframes
Turns a weekly changelog markdown file into a branded HyperFrames video with voiceover, animated mock-UI scenes and captions, using fonts, background and scripts bundled in the skill.
anthropics/skills
Applies Anthropic's brand colors and fonts to artifacts such as PowerPoint slides, using fixed hex values for text and accents, Poppins headings and Lora body text.
harry0703/MoneyPrinterTurbo
Installs and runs MoneyPrinterTurbo to turn a topic or script into a finished short video with voice-over, subtitles, stock footage and music.
latent-spaces/brag
Builds a short, shareable launch video with music and motion from a project directory or a website URL, using only tools already on the machine.
heygen-com/hyperframes
Finds, generates and edits media for HyperFrames video projects: music, sound effects, images, icons, logos, voiceovers, captions and color grades.
nodetool-ai/nodetool
Cut a NodeTool timeline to music and shape its pacing — detect the beat grid, place cuts on phrases, pick a cut type, build speed ramps with time remap, and give the piece an arc.
nodetool-ai/nodetool
Add and animate a consistent text layer on an existing NodeTool timeline.
nodetool-ai/nodetool
Choose and animate colour on a NodeTool timeline, including shape and text gradients, colour grades, 3D LUTs, and dither.
nodetool-ai/nodetool
Write a shootable, precisely timed commercial beat sheet and store it as a NodeTool storyboard, with a consistent entity roster behind every shot.
nodetool-ai/nodetool
Direct ElevenLabs speech, dialogue, sound effects and music — the bracketed audio tags v3 acts on and why the voice decides whether a tag lands, stability as the delivery dial, punctuation instead…
nodetool-ai/nodetool
Prompt OpenAI's GPT Image 2 — the five-slot Scene/Subject/Details/Use case/Constraints template it responds to, the change-versus-preserve shape for edits, labelled multi-image compositing, and how…
Categories
Stage the frame on a NodeTool timeline — grids, focal placement, safe areas per aspect ratio, depth layers and parallax, camera moves, and where elements enter and leave. Frame Composition is an agent skill from nodetool-ai/nodetool. Stage the frame on a NodeTool timeline — grids, focal placement, safe areas per aspect ratio, depth layers and parallax, camera moves, and where elements enter and leave.
Frame Composition fits situations like: A layout must survive 16:9 and 9:16; A parallax move; A frame reads flat.
Run `npx skills add nodetool-ai/nodetool --skill frame-composition -a claude-code`. Or copy the skill folder (packages/system-skills/frame-composition in nodetool-ai/nodetool) into .claude/skills/frame-composition in your project. Claude Code loads it when a task matches its description.
Run `npx skills add nodetool-ai/nodetool --skill frame-composition -a codex`. Or copy the skill folder (packages/system-skills/frame-composition in nodetool-ai/nodetool) into .agents/skills/frame-composition in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add nodetool-ai/nodetool --skill frame-composition -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/frame-composition, .gemini/skills/frame-composition, .github/skills/frame-composition and .opencode/skills/frame-composition in your project.
SKILL.md names no scripts, command-line tools or credentials: Frame Composition is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Frame Composition is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.5k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Frame Composition: Guizang Social Cards (op7418/guizang-social-card-skill, 7.4k stars), Weekly Changelog Video (heygen-com/hyperframes, 59k stars), Anthropic Brand Styling (anthropics/skills, 180k stars) and MoneyPrinterTurbo Video Generator (harry0703/MoneyPrinterTurbo, 129k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
nodetool-ai (a GitHub organization) maintains it in nodetool-ai/nodetool, which has 560 GitHub stars. The repository holds 127 skills in this directory. The repository was last updated on October 9, 2026.
Source: nodetool-ai/nodetool on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.