/spine-animation-ai
Create Spine 2D skeletal animations from pre-existing character assets (separated body-part PNGs, atlas spritesheet, or a full character image). Use this skill whenever the user wants to animate a 2D character, create Spine JSON from existing art assets, rig a character with
$ npx -y skills add GenielabsOpenSource/spine-animation-ai --skill spine-animation-ai --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/spine-animation-ai
Context preview
The summary Claude sees to decide when to auto-load this skill.
Create Spine 2D skeletal animations from pre-existing character assets (separated body-part PNGs, atlas spritesheet, or a full character image). Use this skill whenever the user wants to animate a 2D character, create Spine JSON from existing art assets, rig a character with
SKILL.md
spine-animation-ai.SKILL.mdname: spine-animation
description: >
Create Spine 2D skeletal animations from pre-existing character assets (separated body-part PNGs,
atlas spritesheet, or a full character image). Use this skill whenever the user wants to animate
a 2D character, create Spine JSON from existing art assets, rig a character with bones, build
walk/idle/run/attack animations, produce an interactive Spine Web Player preview, or generate
Spine-compatible export files (.json + .atlas + .png). Also trigger when the user mentions
"Spine animation", "2D rigging", "skeletal animation", "bone animation", "cutout animation",
"animate this character", "make this walk", "create walk cycle", or uploads separated character
body parts and wants them animated. This skill handles the full pipeline: asset analysis,
skeleton rigging, animation keyframing, Spine JSON export, and interactive HTML5 preview.
<!-- ⚠️ AUTO-GENERATED FILE — DO NOT EDIT DIRECTLY Edit SKILL.template.md instead, then push to trigger rebuild. Scripts are embedded automatically by build_skill.py via GitHub Actions. -->
Spine Animation Skill
Turn pre-existing 2D character assets into fully animated, interactive Spine animations.
Step 0: Set Up Scripts
This skill includes Python scripts that do the heavy lifting. Claude MUST write them to disk before use. Each script is embedded below — Claude should save them to `/home/claude/spine-scripts/` at the start of every session.
mkdir -p /home/claude/spine-scripts
pip install opencv-python Pillow numpy google-generativeai --break-system-packages -q
Embedded Scripts
The following scripts are auto-injected from the repository's `scripts/` directory. **Claude: read these carefully, then write each one to `/home/claude/spine-scripts/`** before running the pipeline.
<!-- EMBED:scripts/split_character.py --> <details> <summary>📄 <code>scripts/split_character.py</code> (231 lines)</summary>
#!/usr/bin/env python3
"""
split_character.py — Generate a sprite-sheet atlas from a full character image
using Google Gemini image generation, then segment individual body parts via
OpenCV connected-components analysis.
Usage:
python split_character.py <input_image> [--output-dir output_parts]
[--atlas-out atlas.png] [--min-area 500] [--padding 12]
[--bg-threshold 240]
Requires:
pip install google-generativeai opencv-python Pillow numpy
Environment variable GEMINI_API_KEY must be set.
"""
import argparse
import os
import sys
import cv2
import numpy as np
from PIL import Image
def get_gemini_client():
"""Initialise the Gemini generative-AI client, or exit with a helpful
error if the API key is missing."""
api_key = os.environ.get("GEMINI_API_KEY")
if not api_key:
print(
"ERROR: GEMINI_API_KEY environment variable is not set.\n"
"Get a free API key at: https://aistudio.google.com/app/apikey\n"
"Then run:\n"
" export GEMINI_API_KEY=your_key_here",
file=sys.stderr,
)
sys.exit(1)
from google import genai
client = genai.Client(api_key=api_key)
return client
POSITIVE_PROMPT = (
"A complete 2D game sprite sheet texture atlas for Spine animation of the "
"exact character in the reference image. The character is completely "
"deconstructed into separated, isolated body parts. Separated individual "
"parts laid out flatly: isolated head, isolated torso, isolated upper arms, "
"lower arms, hands, upper legs, lower legs, and feet. Spread out with clear "
"space between every single body part. No overlapping parts. Clean solid "
"white background. CRITICAL: Maintain the exact same art style, exact same "
"shading, exact face, and exact color palette as the reference image. "
"Identical style match, 2D game asset, flat layout, character design sheet."
)
NEGATIVE_PROMPT = (
"3D, realistic, altered style, different art style, different face, "
"redesign, overlapping parts, connected limbs, full body standing, dynamic "
"pose, background scenery, shadows, gradients on background, messy layout, "
"missing limbs, merged layers, text, watermarks."
)
def generate_atlas(client, input_image_path: str, atlas_out: str) -> str:
"""Send the reference image to Gemini and save the generated atlas PNG."""
from google.genai import types
ref_image = Image.open(input_image_path)
response = client.models.generate_content(
model="gemini-3.1-flash-image-preview",
contents=[
POSITIVE_PROMPT,
f"Negative prompt: {NEGATIVE_PROMPT}",
ref_image,
],
config=types.GenerateContentConfig(
response_modalities=["IMAGE", "TEXT"],
),
)
# Extract the generated image from the response parts
for part in response.candidates[0].content.parts:
if part.inline_data is not None:
image_data = part.inline_data.data
with open(atlas_out, "wb") as f:
f.write(image_data)
return atlas_out
print("ERROR: Gemini did not return an image in its response.", file=sys.stderr)
sys.exit(1)
def segment_parts(
atlas_path: str,
output_dir: str,
min_area: int = 500,
padding: int = 12,
bg_threshold: int = 240,
) -> list[str]:
"""Detect individual parts in the atlas using connected-components analysis.
Returns a list of saved part file paths.
"""
img = cv2.imread(atlas_path, cv2.IMREAD_UNCHANGED)
if img is None:
print(f"ERROR: Could not read atlas image: {atlas_path}", file=sys.stderr)
sys.exit(1)
# Convert to RGBA if needed
if img.shape[2] == 3:
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
# Build a foreground mask: pixels whose RGB channels are all below the
# background threshold are considered foreground.
bgr = img[:, :, :3]
gray = cv2.cvtColor(bgr, cv2.Read more
name: spine-animation description: > Create Spine 2D skeletal animations from pre-existing character assets (separated body-part PNGs, atlas spritesheet, or a full character image). Use this skill whenever the user wants to animate a 2D character, create Spine JSON from existing art assets, rig a character with bones, build walk/idle/run/attack animations, produce an interactive Spine Web Player preview, or generate Spine-compatible export files (.json + .atlas + .png). Also trigger when the user mentions "Spine animation", "2D rigging", "skeletal animation", "bone animation", "cutout animation", "animate this character", "make this walk", "create walk cycle", or uploads separated character body parts and wants them animated. This skill handles the full pipeline: asset analysis, skeleton rigging, animation keyframing, Spine JSON export, and interactive HTML5 preview.
<!-- ⚠️ AUTO-GENERATED FILE — DO NOT EDIT DIRECTLY Edit SKILL.template.md instead, then push to trigger rebuild. Scripts are embedded automatically by build_skill.py via GitHub Actions. -->
Spine Animation Skill
Turn pre-existing 2D character assets into fully animated, interactive Spine animations.
Step 0: Set Up Scripts
This skill includes Python scripts that do the heavy lifting. Claude MUST write them to disk before use. Each script is embedded below — Claude should save them to `/home/claude/spine-scripts/` at the start of every session.
mkdir -p /home/claude/spine-scripts pip install opencv-python Pillow numpy google-generativeai --break-system-packages -q
Embedded Scripts
The following scripts are auto-injected from the repository's `scripts/` directory. **Claude: read these carefully, then write each one to `/home/claude/spine-scripts/`** before running the pipeline.
<!-- EMBED:scripts/split_character.py --> <details> <summary>📄 <code>scripts/split_character.py</code> (231 lines)</summary>
#!/usr/bin/env python3
"""
split_character.py — Generate a sprite-sheet atlas from a full character image
using Google Gemini image generation, then segment individual body parts via
OpenCV connected-components analysis.
Usage:
python split_character.py <input_image> [--output-dir output_parts]
[--atlas-out atlas.png] [--min-area 500] [--padding 12]
[--bg-threshold 240]
Requires:
pip install google-generativeai opencv-python Pillow numpy
Environment variable GEMINI_API_KEY must be set.
"""
import argparse
import os
import sys
import cv2
import numpy as np
from PIL import Image
def get_gemini_client():
"""Initialise the Gemini generative-AI client, or exit with a helpful
error if the API key is missing."""
api_key = os.environ.get("GEMINI_API_KEY")
if not api_key:
print(
"ERROR: GEMINI_API_KEY environment variable is not set.\n"
"Get a free API key at: https://aistudio.google.com/app/apikey\n"
"Then run:\n"
" export GEMINI_API_KEY=your_key_here",
file=sys.stderr,
)
sys.exit(1)
from google import genai
client = genai.Client(api_key=api_key)
return client
POSITIVE_PROMPT = (
"A complete 2D game sprite sheet texture atlas for Spine animation of the "
"exact character in the reference image. The character is completely "
"deconstructed into separated, isolated body parts. Separated individual "
"parts laid out flatly: isolated head, isolated torso, isolated upper arms, "
"lower arms, hands, upper legs, lower legs, and feet. Spread out with clear "
"space between every single body part. No overlapping parts. Clean solid "
"white background. CRITICAL: Maintain the exact same art style, exact same "
"shading, exact face, and exact color palette as the reference image. "
"Identical style match, 2D game asset, flat layout, character design sheet."
)
NEGATIVE_PROMPT = (
"3D, realistic, altered style, different art style, different face, "
"redesign, overlapping parts, connected limbs, full body standing, dynamic "
"pose, background scenery, shadows, gradients on background, messy layout, "
"missing limbs, merged layers, text, watermarks."
)
def generate_atlas(client, input_image_path: str, atlas_out: str) -> str:
"""Send the reference image to Gemini and save the generated atlas PNG."""
from google.genai import types
ref_image = Image.open(input_image_path)
response = client.models.generate_content(
model="gemini-3.1-flash-image-preview",
contents=[
POSITIVE_PROMPT,
f"Negative prompt: {NEGATIVE_PROMPT}",
ref_image,
],
config=types.GenerateContentConfig(
response_modalities=["IMAGE", "TEXT"],
),
)
# Extract the generated image from the response parts
for part in response.candidates[0].content.parts:
if part.inline_data is not None:
image_data = part.inline_data.data
with open(atlas_out, "wb") as f:
f.write(image_data)
return atlas_out
print("ERROR: Gemini did not return an image in its response.", file=sys.stderr)
sys.exit(1)
def segment_parts(
atlas_path: str,
output_dir: str,
min_area: int = 500,
padding: int = 12,
bg_threshold: int = 240,
) -> list[str]:
"""Detect individual parts in the atlas using connected-components analysis.
Returns a list of saved part file paths.
"""
img = cv2.imread(atlas_path, cv2.IMREAD_UNCHANGED)
if img is None:
print(f"ERROR: Could not read atlas image: {atlas_path}", file=sys.stderr)
sys.exit(1)
# Convert to RGBA if needed
if img.shape[2] == 3:
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
# Build a foreground mask: pixels whose RGB channels are all below the
# background threshold are considered foreground.
bgr = img[:, :, :3]
gray = cv2.cvtColor(bgr, cv2.An AI-powered Claude skill for creating, rigging, and refining Spine 2D skeletal animations — from raw assets to interactive previews. ▶ Live Animation Preview · 🎛 Interactive Part Editor

