Dotlottie Web
LottieFiles/dotlottie-web
Implement Lottie animations using dotLottie runtimes (@lottiefiles/dotlottie-web and @lottiefiles/dotlottie-react).
Write NodeTool timeline animation curves by hand or bake a JavaScript body into curves once.
$ npx skills add nodetool-ai/nodetool --skill motion-curves -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install nodetool-ai/nodetool motion-curves --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/motion-curves .claude/skills/motion-curves && 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 "motion-curves" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/motion-curves into .claude/skills/motion-curves/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "motion-curves", 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/motion-curvesType 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 motion-curves -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install nodetool-ai/nodetool motion-curves --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/motion-curves .agents/skills/motion-curves && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "motion-curves" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/motion-curves into .agents/skills/motion-curves/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "motion-curves", 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 motion-curves -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install nodetool-ai/nodetool motion-curves --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/motion-curves .cursor/skills/motion-curves && 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 "motion-curves" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/motion-curves into .cursor/skills/motion-curves/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "motion-curves", 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/motion-curves--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 motion-curves -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install nodetool-ai/nodetool motion-curves --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/motion-curves .gemini/skills/motion-curves && 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 "motion-curves" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/motion-curves into .gemini/skills/motion-curves/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "motion-curves", 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 motion-curvesInstalls 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 motion-curves -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/motion-curves .github/skills/motion-curves && 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 "motion-curves" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/motion-curves into .github/skills/motion-curves/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "motion-curves", 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 motion-curves -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 motion-curves --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/motion-curves .opencode/skills/motion-curves && 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 "motion-curves" agent skill from https://github.com/nodetool-ai/nodetool/tree/main/packages/system-skills/motion-curves into .opencode/skills/motion-curves/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "motion-curves", 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.
motion-curvesWrite NodeTool timeline animation curves by hand or bake a JavaScript body into curves once.
Motion Curves is an agent skill from nodetool-ai/nodetool. Write NodeTool timeline animation curves by hand or bake a JavaScript body into curves once. Use for overshoot, bounce, anticipation, arcs, path draw-on, style-property animation, or motion a preset cannot express.
Its SKILL.md is about 3.2k 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. It works with JavaScript. The repository describes itself as: Agent-first Creative Workspace. The licence is AGPL-3.0.
Read from SKILL.md and the folder at commit 339f069. 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.
Motion Curves loads about 3.2k tokens when it runs. Until then it costs about 57 tokens; SKILL.md has 1,367 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 339f069, republished under its AGPL-3.0 licence (© nodetool-ai). 1,367 words, ~3,164 tokens.
.claude/skills/motion-curves/SKILL.md (or your agent's skills folder).An animate_clip input with {"preset":"custom"} carries exactly one of
curves (keyframes you write) or code (a JS body baked into curves once,
host-side). Add mask when a curve drives wipeProgress. A stored document
animation can instead carry styleTracks or textAnimator without numeric
custom curves.
motion-graphics carries the op contract and the preset catalog this file is
the escape hatch from. motion-principles gives the duration and the shape a
curve should hit before you write its keyframes.
For numeric custom curves, call edit_timeline with an animate_clip op or
the in-product ui_timeline_animate_clip tool. Both accept the flat curves
or code input shown below. For stored styleTracks, textAnimator, or
beat, read get_timeline, edit the full clip animation in its document,
then call set_timeline_document with every existing document field. The
animate_clip input does not author those stored fields.
Write curves as soon as a preset is close but not right. The catalog is seven
entrance shapes and a handful of beats — where motion starts, not where it
stops — and a piece whose every title arrives with pop reads like a template.
A curve costs one field and a few numbers, and the recipes below are the shapes
worth reaching for: an entrance that overshoots twice, a hold in the middle of a
move, two channels on different schedules, a decay, an arc, a wiggle, a path
draw-on.
Two shapes need no curve, and writing one anyway only makes the document harder
to read: a single overshoot and a physical settle are already easing strings.
cubic-bezier(0.16,1,0.3,1) and spring(180,12,1) on an ordinary preset do
both. Everything past that is this file.
{"op": "animate_clip", "target": "Title", "animations": [
{"role": "in", "preset": "custom", "durationMs": 600,
"curves": [
{"property": "offsetY", "keyframes": [
{"t": 0, "value": 80}, {"t": 0.7, "value": -12, "easing": "easeOut"},
{"t": 1, "value": 0, "easing": "easeInOut"}]},
{"property": "opacity", "keyframes": [
{"t": 0, "value": 0}, {"t": 0.4, "value": 1}]}]}]}t runs 0..1 over the animation's window, not the clip. easing on a
keyframe eases the segment ending there. Keyframes are sorted, t is clamped
to 0..1, and a curve that stops short of either end is extended by holding its
end value — so sampling 0.05..0.95 does what it looks like.
Limits: 16 curves per animation, one per property, 4096 keyframes each.
durationMs defaults to the clip's own duration, so curves span the whole clip
unless you say otherwise.
Several animations can drive one channel. How they fold decides whether the second adds to the first or throws it away.
| Fold | Channels | Identity | Result |
|---|---|---|---|
| add | offsetX, offsetY, rotation (radians), blur (px), brightness (−1..1), hue (deg), temperature, tint | 0 | Values sum |
| multiply | scale, scaleX, scaleY, opacity (0..1), saturation (0..4), contrast (0..4) | 1 | Values multiply |
| min | wipeProgress (0..1) | 1 | The tightest wipe wins |
| replace | positionX, positionY (canvas px), anchorX, anchorY (0..1), trimStart, trimEnd (0..1) | none | The last animation in document order wins; the other is discarded |
The replace row is the trap. Two animations driving positionX over the same
instants means one does nothing, reported as replace_curves_overlap. Move a
clip with offsetX when it should compose with other motion, and with
positionX only for an absolute placement nothing else touches.
Land the last keyframe on the identity value unless you mean the clip to stay
where the curve stopped — and remember the role decides whether it stays: an
in window holds its t: 0 values before it and contributes nothing after, an
out window holds its t: 1 values after it, emphasis holds neither, and
loop repeats its cycle, so a loop curve must end on the value it started on.
list_animation_presets reports this table from the engine. Read it there rather
than from memory when a channel's range matters.
Use styleTracks on a stored animation when the target is a visual property
rather than a numeric motion channel. The target names a clip style such as
text.color, shape.cornerRadius, mask.featherPx, or
clip.borderRadius; an effect target is
effect.<effect-id>.<numeric-field> or a supported effect color such as
effect.bg-field.colorB. A target needs the matching style,
mask, or effect on the clip. Color values interpolate through the supported
CSS color parser. shape.d and mask.d paths need matching commands and point
counts. Glyph targets need a text stagger. validate_timeline reports an
invalid target, incompatible path, or unsupported color.
This is one complete stored animation object to merge into an existing clip's
animations array before the full-document write:
{"id":"round-in","role":"in","preset":"fade","durationMs":600,"styleTracks":[{"target":"clip.borderRadius","keyframes":[{"t":0,"value":0},{"t":1,"value":30,"easing":"easeOutExpo"}]}]}styleTracks can accompany a preset, so a title can fade while its color
changes. The id is required in the stored document; animate_clip creates
one for its own inputs. Use motion-graphics for links, text animators, beat
binding, and the document write boundary.
A JavaScript body run once, at author time, in the QuickJS sandbox. It returns keyframes; the keyframes are stored on the clip; every renderer samples those. Nothing evaluates per frame, which is why a body cannot react to playback and why the same animation looks identical in the preview, the export and the headless compositor.
The bake is hermetic: no toolbelt, no nodetool.*, no network, no secrets. Just
arithmetic, a 10-second ceiling, and inputs:
inputs field | What it is |
|---|---|
role | in, out, emphasis or loop |
durationMs | The animation's own window |
clipDurationMs | The clip it sits on |
canvasWidth, canvasHeight | Sequence pixels — turn a normalized distance into px here |
params | The animation's params, untouched |
staggerCount | Units a text clip splits into, or 0 |
sampleCount | Suggested density for a continuous function |
Return {curves} — the same shape as the JSON above — or {samples}, one bag
per point in time:
const n = inputs.sampleCount;
const samples = [];
for (let i = 0; i < n; i++) {
const t = i / (n - 1);
samples.push({ t, offsetY: 80 * (1 - t), opacity: t });
}
return { samples };Returning both is an error, as is returning neither. A property present on some
samples and absent from others is an error rather than a hole — interpolating
across the gap would invent motion nobody wrote. A sample needs a finite numeric
t; easing on a sample is optional and applies to the segment ending there.
At most 4096 samples.
Because the bake runs once, a body using Math.random is frozen at the value it
drew: the result is stable forever after, but re-baking gives different motion.
Seed your own generator when the same body has to produce the same wiggle twice.
Overshoot and settle. Two overshoots, the second smaller — what a single
easeOutBack cannot express.
const p = [[0, 0.6], [0.45, 1.09], [0.68, 0.97], [0.85, 1.02], [1, 1]];
return { curves: [{ property: "scale",
keyframes: p.map(([t, value]) => ({ t, value, easing: "easeInOut" })) }] };Decaying bounce. Hops that die out and land exactly at rest.
const n = inputs.sampleCount, h = 0.06 * inputs.canvasHeight, hops = 3;
const samples = [];
for (let i = 0; i < n; i++) {
const t = i / (n - 1);
samples.push({ t, offsetY: -h * Math.abs(Math.sin(Math.PI * hops * t)) * (1 - t) });
}
return { samples };Anticipation. A counter-move before the action, 60–120ms of the window.
return { curves: [{ property: "offsetY", keyframes: [
{ t: 0, value: 0 }, { t: 0.18, value: 10, easing: "easeInOut" },
{ t: 0.8, value: -4, easing: "easeOut" }, { t: 1, value: 0 }] }] };Shaped wiggle. For a steady seeded wiggle, use a stored
animationLinks entry with kind: "wiggle" as described in
motion-graphics. Bake a curve when its amplitude must fade in or out. This
seeded generator reproduces the same shape on a re-bake.
const n = inputs.sampleCount;
const amp = Number(inputs.params.amplitude ?? 6);
let seed = Number(inputs.params.seed ?? 1);
const rand = () => (seed = (seed * 1103515245 + 12345) % 2147483648) / 2147483648 - 0.5;
const samples = [];
for (let i = 0; i < n; i++) {
const t = i / (n - 1);
const fade = Math.min(1, 4 * t, 4 * (1 - t)); // rest at both ends
samples.push({ t, offsetX: rand() * amp * fade, offsetY: rand() * amp * fade });
}
return { samples };Inertia. A trailing part that lags the body and catches up — follow-through without a second clip.
const n = inputs.sampleCount, lag = 0.12;
const ease = (t) => 1 - Math.pow(1 - t, 3);
const samples = [];
for (let i = 0; i < n; i++) {
const t = i / (n - 1);
const behind = ease(Math.max(0, t - lag) / (1 - lag));
samples.push({ t, offsetX: (1 - behind) * -0.1 * inputs.canvasWidth });
}
return { samples };Arc. Straight-line travel looks mechanical. Drive one axis linearly and the
other as a shallow parabola over the same window; both fold as add.
const n = inputs.sampleCount;
const dx = 0.25 * inputs.canvasWidth, rise = 0.06 * inputs.canvasHeight;
const samples = [];
for (let i = 0; i < n; i++) {
const t = i / (n - 1);
samples.push({ t, offsetX: -dx * (1 - t), offsetY: -rise * 4 * t * (1 - t) });
}
return { samples };Pendulum. A decaying rotation, in radians.
const n = inputs.sampleCount, a = 0.12, cycles = 2.5;
const samples = [];
for (let i = 0; i < n; i++) {
const t = i / (n - 1);
samples.push({ t, rotation: a * Math.cos(2 * Math.PI * cycles * t) * (1 - t) });
}
return { samples };A loop with no visible join. Any loop curve must return to its start, so
build it from a whole number of cycles of a periodic function.
const n = inputs.sampleCount, amp = 0.02 * inputs.canvasHeight;
const samples = [];
for (let i = 0; i < n; i++) {
const t = i / (n - 1);
samples.push({ t, offsetY: -amp * Math.sin(2 * Math.PI * t) });
}
return { samples };Path draw-on. trimEnd 0 to 1 on a path shape clip. Both trim channels
fold as replace, so one animation drives each and their windows must not
overlap.
return { curves: [{ property: "trimEnd",
keyframes: [{ t: 0, value: 0 }, { t: 1, value: 1, easing: "easeInOut" }] }] };Wipe with a shaped edge. A wipeProgress curve needs the mask on the same
animation, because direction and softness cannot be inferred:
{"role": "in", "preset": "custom", "durationMs": 700,
"mask": {"direction": "left", "softness": 0.1},
"curves": [{"property": "wipeProgress", "keyframes": [
{"t": 0, "value": 0}, {"t": 0.6, "value": 0.8, "easing": "easeOut"},
{"t": 1, "value": 1}]}]}wipeProgress with no mask is refused.unknown_easing on validate_timeline. It is easeOut, not ease-out.animation_exceeds_clip
— the motion is clamped or never runs.Curves are the one place where reading the numbers is not enough. Use
preview_timeline_frame with a range across the animation's window and
sheet: true, which tiles the sweep into one labelled contact sheet — the way
to watch an overshoot actually overshoot rather than checking three instants
that all happen to look right.
© 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/motion-curves of nodetool-ai/nodetool.
Open the folder on GitHubat commit 339f069
Motion Curves 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 |
|---|---|---|---|---|---|---|
| Motion Curves this skillnodetool-ai/nodetool | 560 | — | ~3.2k | Automated safety check: Pass | AGPL-3.0 | |
| Dotlottie WebLottieFiles/dotlottie-web | 892 | — | ~3.5k | Automated safety check: Pass | MIT | |
| Speech To Texttadaspetra/loop | 296 | 2 repos | ~2k | Automated safety check: Pass | MIT | |
| HTML DesignNimaChu/html-design | 101 | — | ~2.7k | Automated safety check: Pass | None | |
| Explainroovincentsch/explainroo | 515 | — | ~439 | Automated safety check: Pass | MIT | |
| OneWorks 3D Avatar Designeroneworks-ai/avatar | 251 | — | ~1.7k | Automated safety check: Pass | MIT |
LottieFiles/dotlottie-web
Implement Lottie animations using dotLottie runtimes (@lottiefiles/dotlottie-web and @lottiefiles/dotlottie-react).
tadaspetra/loop
Transcribe audio to text using ElevenLabs Scribe v2. An agent skill from tadaspetra/loop.
NimaChu/html-design
Create, redesign, repair, validate, preview, and package lightweight standalone HTML deliverables.
vincentsch/explainroo
Make an explainer video (MP4) with a voice-over using explainroo.
oneworks-ai/avatar
Creates, refines and exports editable OneWorks 3D geometric avatars for mascots, bots or agents, keeping one shared scene state across preview, share link and export.
deepgram/deepgram-js-sdk
A skill your agent uses when writing or reviewing JavaScript/TypeScript in this repo that calls Deepgram audio analytics overlays on /v1/listen - summarize, topics, intents, sentiment, diarize…
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
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.
Works with
Categories
Write NodeTool timeline animation curves by hand or bake a JavaScript body into curves once. Motion Curves is an agent skill from nodetool-ai/nodetool. Write NodeTool timeline animation curves by hand or bake a JavaScript body into curves once.
Motion Curves fits situations like: style-property animation; motion a preset cannot express.
Run `npx skills add nodetool-ai/nodetool --skill motion-curves -a claude-code`. Or copy the skill folder (packages/system-skills/motion-curves in nodetool-ai/nodetool) into .claude/skills/motion-curves in your project. Claude Code loads it when a task matches its description.
Run `npx skills add nodetool-ai/nodetool --skill motion-curves -a codex`. Or copy the skill folder (packages/system-skills/motion-curves in nodetool-ai/nodetool) into .agents/skills/motion-curves 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 motion-curves -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/motion-curves, .gemini/skills/motion-curves, .github/skills/motion-curves and .opencode/skills/motion-curves in your project.
SKILL.md names no scripts, command-line tools or credentials: Motion Curves 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.
Motion Curves 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.2k tokens (SKILL.md is roughly 13k 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 Motion Curves: Dotlottie Web (LottieFiles/dotlottie-web, 892 stars), Speech To Text (tadaspetra/loop, 296 stars), HTML Design (NimaChu/html-design, 101 stars) and Explainroo (vincentsch/explainroo, 515 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 10, 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.