stix
npx skills add https://github.com/bassimeledath/stix --skill stix
Agent 安装分布
Skill 文档
/stix â Stick Figure Animation
Generate stick figure animations from natural language descriptions. Outputs GIF and MP4 files.
Usage
/stix "a cat chasing a mouse across a park"
Pipeline
When the user invokes /stix, execute these steps in order:
Step 1: Parameter Inference
Parse the user’s prompt and infer these parameters. The user never sees or sets these directly â infer them from the natural language description:
| Parameter | Range | Default | How to infer |
|---|---|---|---|
scenes |
1â6 | 2 | Count distinct moments/locations/emotional beats in the prompt |
fps |
8â24 | 8 | Default for most; use 12 for fast action |
format |
gif/mp4/both | both | Default both unless user specifies |
mood |
playful/melancholy/energetic/calm | playful | Infer from the emotion in the prompt |
Each scene is always 8 seconds (the animation system is built around this fixed duration).
Write these to .stix/params.json:
{
"prompt": "a cat chasing a mouse across a park",
"scenes": 3,
"fps": 8,
"format": "both",
"mood": "playful"
}
Step 2: Preflight Checks
Verify dependencies are installed:
command -v agent-browser >/dev/null 2>&1 || { echo "â agent-browser not found"; exit 1; }
command -v ffmpeg >/dev/null 2>&1 || { echo "â ffmpeg not found"; exit 1; }
# Detect agent CLI (configurable via STIX_AGENT_CLI env var)
STIX_AGENT_CLI="${STIX_AGENT_CLI:-}"
if [ -z "$STIX_AGENT_CLI" ]; then
if command -v claude >/dev/null 2>&1; then
STIX_AGENT_CLI="claude -p --dangerously-skip-permissions"
STIX_AGENT_ENV_UNSET="CLAUDE_CODE_ENTRYPOINT,CLAUDECODE"
elif command -v codex >/dev/null 2>&1; then
STIX_AGENT_CLI="codex --quiet --full-auto"
STIX_AGENT_ENV_UNSET=""
else
echo "â No supported agent CLI found. Set STIX_AGENT_CLI env var."
echo " Supported: claude, codex. Or set STIX_AGENT_CLI to your agent's pipe command."
exit 1
fi
fi
AGENT_BIN=$(echo "$STIX_AGENT_CLI" | awk '{print $1}')
command -v "$AGENT_BIN" >/dev/null 2>&1 || { echo "â Agent CLI '$AGENT_BIN' not found"; exit 1; }
Create the working directory:
rm -rf .stix
mkdir -p .stix/scenes .stix/qc .stix/output
Step 3: Story Decomposition
Break the prompt into scenes. Write .stix/story.json:
{
"title": "Cat Chases Mouse",
"scenes": [
{
"id": 1,
"description": "A mouse scurries across a park path, unaware. Trees and a bench in background.",
"characters": ["mouse"],
"start_pose": "standing",
"end_pose": "running",
"props": ["tree", "bench"],
"mood": "playful",
"key_action": "Mouse enters from left and runs across screen"
},
{
"id": 2,
"description": "A cat spots the mouse and launches into a chase. Both running across the park.",
"characters": ["cat", "mouse"],
"start_pose": "crouching",
"end_pose": "running",
"props": ["tree"],
"mood": "energetic",
"key_action": "Cat enters chasing mouse, both running right",
"continuity": "Mouse position matches end of scene 1"
}
]
}
Continuity rules:
- Last frame of scene N must match first frame of scene N+1 in character position, pose, and visible props
- Characters that exit a scene should enter the next scene from the same direction
- Emotional progression must be logical
Step 4: Scene Generation (Parallel Workers)
For each scene, spawn a background worker using the agent CLI. All workers run in parallel.
Read the scene count from story.json:
TOTAL_SCENES=$(python3 -c "import json; print(len(json.load(open('.stix/story.json'))['scenes']))")
The dispatcher must read and inject all library file contents into each worker prompt. Workers run as independent agent subprocesses and cannot access the skill directory. The dispatcher is responsible for assembling the full prompt with all necessary context inline.
For each scene N:
- Build the worker prompt by reading and injecting library contents:
SKILL_DIR="$(dirname "$(readlink -f "$0")" 2>/dev/null || cd "$(dirname "$0")" && pwd)"
# If SKILL_DIR detection fails, try common install locations:
# ~/.claude/skills/stix, ~/.codex/skills/stix, or ~/.agents/skills/stix
# Read all library files into variables
STYLE_GUIDE="$(cat "$SKILL_DIR/library/style-guide.md")"
POSES="$(cat "$SKILL_DIR/library/poses.md")"
TRANSITIONS="$(cat "$SKILL_DIR/library/transitions.md")"
EXPRESSIONS="$(cat "$SKILL_DIR/library/expressions.md")"
PROPS="$(cat "$SKILL_DIR/library/props.md")"
ANIMALS="$(cat "$SKILL_DIR/library/animals.md")"
BASE_TEMPLATE="$(cat "$SKILL_DIR/references/scene-base.html")"
# Read this scene's description from story.json
SCENE_DESC=$(python3 -c "
import json
story = json.load(open('.stix/story.json'))
scene = story['scenes'][$((N-1))]
print(json.dumps(scene, indent=2))
")
# Assemble the prompt with all library contents injected inline
cat > /tmp/stix-scene-$(printf "%02d" $N)-prompt.txt << PROMPT_EOF
You are generating a single HTML file for a stick figure animation scene.
## Scene Specification
$SCENE_DESC
## Component Library
### Style Guide
$STYLE_GUIDE
### Poses
$POSES
### Transitions
$TRANSITIONS
### Expressions
$EXPRESSIONS
### Props
$PROPS
### Animals
$ANIMALS
## Base Template
$BASE_TEMPLATE
## Rules
1. Use CSS-only animation (no JavaScript)
2. All animations loop with \`infinite\` and duration \`8s\`
3. Use the relative coordinate system from the style guide
4. Position characters via \`translate()\` on parent \`<g>\` elements
5. Match poses and props from the component library exactly
6. Use the color palette from the style guide
7. Sub-loops (walk cycle 0.5s, run cycle 0.4s) nest inside the 8s scene loop
8. Include the ground line at y=355
## Output
Write ONLY the complete HTML file to: .stix/scenes/scene-$(printf "%02d" $N).html
No explanation, no markdown â just the HTML file.
PROMPT_EOF
- Spawn the worker (use the most capable available model for generation):
# Build env unset command
ENV_CMD="env"
if [ -n "$STIX_AGENT_ENV_UNSET" ]; then
IFS=',' read -ra UNSET_VARS <<< "$STIX_AGENT_ENV_UNSET"
for var in "${UNSET_VARS[@]}"; do
[ -n "$var" ] && ENV_CMD="$ENV_CMD -u $var"
done
fi
$ENV_CMD $STIX_AGENT_CLI \
"$(cat /tmp/stix-scene-$(printf "%02d" $N)-prompt.txt)" &
- After spawning all workers, wait for completion:
wait
- Verify all scene files exist:
for N in $(seq 1 $TOTAL_SCENES); do
FILE=".stix/scenes/scene-$(printf "%02d" $N).html"
if [ ! -f "$FILE" ]; then
echo "â Missing: $FILE"
exit 1
fi
echo "â $FILE generated"
done
Step 5: Visual QC
For each scene, perform quality checks using screenshots and a review worker.
Per scene:
- Capture 4 keyframes:
SCENE_FILE=".stix/scenes/scene-$(printf "%02d" $N).html"
ABS_PATH="$(cd "$(dirname "$SCENE_FILE")" && pwd)/$(basename "$SCENE_FILE")"
agent-browser open "file://$ABS_PATH"
sleep 0.5
# Keyframe at 0%
agent-browser screenshot ".stix/qc/scene-${N}-kf0.png"
# Keyframe at 33% (sleep 2.64s into 8s loop)
sleep 2.64
agent-browser screenshot ".stix/qc/scene-${N}-kf33.png"
# Keyframe at 66%
sleep 2.64
agent-browser screenshot ".stix/qc/scene-${N}-kf66.png"
# Keyframe at 100%
sleep 2.64
agent-browser screenshot ".stix/qc/scene-${N}-kf100.png"
agent-browser close
- Spawn a QC reviewer (use a fast model â review-tier is sufficient for visual review):
# Read the QC rubric
QC_RUBRIC="$(cat "$SKILL_DIR/references/qc-rubric.md")"
# Read this scene's description
SCENE_DESC=$(python3 -c "
import json
story = json.load(open('.stix/story.json'))
scene = story['scenes'][$((N-1))]
print(json.dumps(scene, indent=2))
")
cat > /tmp/stix-qc-$(printf "%02d" $N)-prompt.txt << QC_EOF
Review these 4 keyframe screenshots of a stick figure animation scene against the QC rubric.
Screenshots:
- .stix/qc/scene-${N}-kf0.png (0% - start)
- .stix/qc/scene-${N}-kf33.png (33%)
- .stix/qc/scene-${N}-kf66.png (66%)
- .stix/qc/scene-${N}-kf100.png (100% - end)
QC Rubric:
$QC_RUBRIC
Scene description:
$SCENE_DESC
Evaluate each category: Character Integrity, Animation Correctness, Scene Composition, Visual Quality.
Output a JSON object:
{
"scene": $N,
"overall": "PASS" or "FAIL",
"categories": {
"character_integrity": { "result": "PASS/FAIL", "notes": "..." },
"animation_correctness": { "result": "PASS/FAIL", "notes": "..." },
"scene_composition": { "result": "PASS/FAIL", "notes": "..." },
"visual_quality": { "result": "PASS/FAIL", "notes": "..." }
},
"fix_instructions": ["list of specific fixes needed"]
}
Write the result to: .stix/qc/scene-${N}-result.json
QC_EOF
# Build env unset command
ENV_CMD="env"
if [ -n "$STIX_AGENT_ENV_UNSET" ]; then
IFS=',' read -ra UNSET_VARS <<< "$STIX_AGENT_ENV_UNSET"
for var in "${UNSET_VARS[@]}"; do
[ -n "$var" ] && ENV_CMD="$ENV_CMD -u $var"
done
fi
$ENV_CMD $STIX_AGENT_CLI \
"$(cat /tmp/stix-qc-$(printf "%02d" $N)-prompt.txt)"
- If FAIL, fix and re-review (max 3 iterations):
ITERATION=0
MAX_ITERATIONS=3
while [ $ITERATION -lt $MAX_ITERATIONS ]; do
# Read QC result
QC_RESULT=$(cat ".stix/qc/scene-${N}-result.json" 2>/dev/null)
if echo "$QC_RESULT" | grep -q '"overall": "PASS"'; then
echo "â Scene $N passed QC"
break
fi
ITERATION=$((ITERATION + 1))
echo "â Scene $N failed QC (attempt $ITERATION/$MAX_ITERATIONS). Fixing..."
# Read current scene HTML
CURRENT_HTML="$(cat ".stix/scenes/scene-$(printf "%02d" $N).html")"
# Spawn fix worker (use the most capable available model)
cat > /tmp/stix-fix-$(printf "%02d" $N)-prompt.txt << FIX_EOF
Fix this stick figure animation scene based on QC feedback.
Current HTML:
$CURRENT_HTML
QC Result:
$QC_RESULT
Component Library:
### Style Guide
$STYLE_GUIDE
### Poses
$POSES
### Transitions
$TRANSITIONS
### Expressions
$EXPRESSIONS
### Props
$PROPS
### Animals
$ANIMALS
Fix the issues listed in fix_instructions. Write the corrected HTML to:
.stix/scenes/scene-$(printf "%02d" $N).html
FIX_EOF
# Build env unset command
ENV_CMD="env"
if [ -n "$STIX_AGENT_ENV_UNSET" ]; then
IFS=',' read -ra UNSET_VARS <<< "$STIX_AGENT_ENV_UNSET"
for var in "${UNSET_VARS[@]}"; do
[ -n "$var" ] && ENV_CMD="$ENV_CMD -u $var"
done
fi
$ENV_CMD $STIX_AGENT_CLI \
"$(cat /tmp/stix-fix-$(printf "%02d" $N)-prompt.txt)"
# Re-capture and re-review
# (repeat keyframe capture + QC review from above)
done
- Continuity check (multi-scene only):
For scenes 2+, compare the last frame of the previous scene with the first frame of the current scene:
PREV=$((N - 1))
cat > /tmp/stix-continuity-prompt.txt << CONT_EOF
Compare these two screenshots for continuity:
1. .stix/qc/scene-${PREV}-kf100.png (end of scene $PREV)
2. .stix/qc/scene-${N}-kf0.png (start of scene $N)
Check:
- Character position consistency
- Pose continuity
- Prop consistency
- Emotional progression
Output: PASS or FAIL with specific fix notes.
Write to: .stix/qc/continuity-${PREV}-${N}.json
CONT_EOF
# Build env unset command
ENV_CMD="env"
if [ -n "$STIX_AGENT_ENV_UNSET" ]; then
IFS=',' read -ra UNSET_VARS <<< "$STIX_AGENT_ENV_UNSET"
for var in "${UNSET_VARS[@]}"; do
[ -n "$var" ] && ENV_CMD="$ENV_CMD -u $var"
done
fi
$ENV_CMD $STIX_AGENT_CLI \
"$(cat /tmp/stix-continuity-prompt.txt)"
Step 6: Frame Capture & Stitch
Run the capture script with inferred parameters:
SKILL_DIR="$(dirname "$(readlink -f "$0")" 2>/dev/null || cd "$(dirname "$0")" && pwd)"
bash "$SKILL_DIR/scripts/capture.sh" \
--scenes-dir .stix/scenes \
--frames-dir .stix/frames \
--output-dir .stix/output \
--fps $FPS \
--format $FORMAT
Step 7: Report
After the pipeline completes, report to the user:
â
Animation complete!
Prompt: "a cat chasing a mouse across a park"
Scenes: 3
Duration: 24s (3 Ã 8s)
FPS: 8
QC: All scenes passed (2 required fixes)
Output:
GIF: .stix/output/animation.gif (270KB)
MP4: .stix/output/animation.mp4 (90KB)
Component Library Reference
When generating scenes, the dispatcher must read these files and inject their full contents into worker prompts:
| File | Purpose |
|---|---|
library/style-guide.md |
Coordinate system, proportions, colors, CSS classes |
library/poses.md |
16 named poses with exact SVG path data |
library/transitions.md |
Animation keyframe patterns (walk, run, sit, jump, etc.) |
library/expressions.md |
9 facial expressions with SVG data |
library/props.md |
Reusable prop SVG snippets |
library/animals.md |
4 animal templates with walk cycles |
Key Conventions
- CSS-only animation â no JavaScript. Deterministic timing, no race conditions.
- 8s scene duration â all
animation-duration: 8swithinfiniteloop. - Relative coordinates â characters defined at origin, positioned via
translate(). - Phase-based scenes â for multi-moment scenes, use opacity toggling (see
transitions.mdâ phase_transition). - Sub-loops â walk cycle (0.5s), run cycle (0.4s) nest inside the 8s scene loop.
- Generation tier for creation, review tier for QC â use your agent’s most capable model for scene generation, the fastest capable model for QC review. The agent CLI handles model selection.
- Max 3 QC fix iterations â if still failing after 3, report the remaining issues to the user.