agentsclimarketplace

Scratch sprite library

Skill yokobond/scratch-skills/skills/scratch-sprite-library

Adds sprites and backdrops from the Scratch built-in library via the editor UI. Use this skill when you need to add pre-made characters, animals, objects, or backgrounds to a Scratch project.From its SKILL.md

Install
npx -y skills add yokobond/scratch-skills --skill scratch-sprite-library

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

12.6 KB, ~3.1k tokens by cl100k_base, as published. Nobody here has run it

Scratch Sprite Library Skill

This skill adds sprites and backdrops to a Scratch project by interacting with the built-in library dialogs in the Scratch editor via the playwright-cli skill.

Prerequisites

This skill drives the browser via the playwright-cli skill. Ensure that skill is installed and a browser session has been opened (e.g. playwright-cli open --headed https://scratch.mit.edu/projects/editor/).

Visibility: Always use --headed when opening the browser so that the Scratch editor is visible to the user during project creation.

When to Use

  • When you need specific characters (animals, people, fantasy creatures, etc.)
  • When you need themed backdrops (outdoor, indoor, space, etc.)
  • When costumes with proper SVG assets and multiple animation frames are needed
  • Prefer this over manual addSprite() with JSON — the old CDN asset URLs (cdn.assets.scratch.mit.edu/internalapi/asset/...) no longer work, so programmatic sprite creation with hardcoded asset IDs will fail to load costumes

Language-Independent Selectors

The Scratch editor supports dynamic language switching. All UI text (button labels, placeholders, category names) changes with the locale. Never use aria-label, placeholder text, or visible text for element selection.

Instead, use CSS class prefix matching. Scratch uses CSS Modules with the pattern {component}_{style}_{hash}. The hash changes per build, but {component}_{style} is stable across builds and locales. Always use [class*="component_style"] selectors.

Selector Reference

ElementSelector
Sprite chooser buttondiv[class*="sprite-selector_add-button"] button[class*="action-menu_main-button"]
Backdrop chooser buttondiv[class*="stage-selector_add-button"] button[class*="action-menu_main-button"]
Library dialogdiv[class*="modal_modal-content"][role="dialog"]
Library search textboxinput[class*="filter_filter-input"]
Library item buttonsbutton[class*="library-item_library-item"]
Library item name spanspan[class*="library-item_library-item-name"]
Category filter buttonsbutton[class*="tag-button_tag-button"]
Active category buttonbutton[class*="tag-button_tag-button"][class*="tag-button_active"]
Library scroll griddiv[class*="library_library-scroll-grid"]
Modal close/back buttondiv[class*="modal_header-item-close"] button

Workflow

1. Open Scratch Editor

playwright-cli open --headed https://scratch.mit.edu/projects/editor/

Wait for the editor to fully load.

2. Open the Sprite Library Dialog

CRITICAL: The sprite chooser button has overlapping sub-buttons that intercept pointer events, causing a normal playwright-cli click to time out. You must use JavaScript click() instead.

playwright-cli run-code "$(cat <<'EOF'
async (page) => {
  await page.evaluate(() => {
    const btn = document.querySelector(
      'div[class*="sprite-selector_add-button"] button[class*="action-menu_main-button"]'
    );
    if (btn) btn.click();
  });
  await page.waitForTimeout(2000);
  return 'Opened sprite library';
}
EOF
)"

3. Search for a Sprite (Optional)

Type into the search box to filter the library. Sprite names are always in English regardless of the editor locale.

playwright-cli run-code "$(cat <<'EOF'
async (page) => {
  const searchBox = page.locator('input[class*="filter_filter-input"]');
  await searchBox.fill('Hare');
  await page.waitForTimeout(1000);
  return 'Searched';
}
EOF
)"

4. Click a Sprite to Add It

Find the library item by matching the name text inside span[class*="library-item_library-item-name"]. The dialog closes automatically after selection.

playwright-cli run-code "$(cat <<'EOF'
async (page) => {
  await page.evaluate((name) => {
    const spans = document.querySelectorAll('span[class*="library-item_library-item-name"]');
    for (const span of spans) {
      if (span.textContent.trim() === name) {
        span.closest('button[class*="library-item_library-item"]').click();
        return;
      }
    }
    throw new Error('Sprite not found: ' + name);
  }, 'Hare');
  await page.waitForTimeout(1000);
  return 'Sprite added';
}
EOF
)"

5. Rename the Sprite (Optional)

After adding, rename the sprite via the VM for localized or custom names:

playwright-cli run-code "$(cat <<'EOF'
async page => await page.evaluate(() => {
  const vm = window.vm;
  const target = vm.runtime.targets.find(t => t.sprite.name === 'Hare');
  if (target) vm.renameSprite(target.id, 'Rabbit');
  return 'Renamed';
})
EOF
)"

6. Repeat for Additional Sprites

To add multiple sprites, repeat steps 2–5 for each one. The library dialog must be re-opened each time since it closes after each selection.

Adding Backdrops

The backdrop library works the same way but uses a different button.

Open Backdrop Library

playwright-cli run-code "$(cat <<'EOF'
async (page) => {
  await page.evaluate(() => {
    const btn = document.querySelector(
      'div[class*="stage-selector_add-button"] button[class*="action-menu_main-button"]'
    );
    if (btn) btn.click();
  });
  await page.waitForTimeout(2000);
  return 'Opened backdrop library';
}
EOF
)"

Search and Select a Backdrop

playwright-cli run-code "$(cat <<'EOF'
async (page) => {
  const searchBox = page.locator('input[class*="filter_filter-input"]');
  await searchBox.fill('Blue Sky');
  await page.waitForTimeout(1000);

  await page.evaluate((name) => {
    const spans = document.querySelectorAll('span[class*="library-item_library-item-name"]');
    for (const span of spans) {
      if (span.textContent.trim() === name) {
        span.closest('button[class*="library-item_library-item"]').click();
        return;
      }
    }
    throw new Error('Backdrop not found: ' + name);
  }, 'Blue Sky');
  await page.waitForTimeout(1000);
  return 'Backdrop added';
}
EOF
)"

Filtering by Category

Category buttons are ordered consistently regardless of locale. Use :nth-child(n) to select by position.

PositionCategory (English)
1All
2Animals
3People
4Fantasy
5Dance
6Music
7Sports
8Food
9Fashion
10Letters
playwright-cli run-code "$(cat <<'EOF'
async (page) => {
  // Click "Animals" category (2nd button)
  await page.evaluate(() => {
    const buttons = document.querySelectorAll('button[class*="tag-button_tag-button"]');
    if (buttons.length >= 2) buttons[1].click(); // 0-indexed
  });
  await page.waitForTimeout(1000);
  return 'Filtered by Animals';
}
EOF
)"

Deleting the Default Sprite

To remove the default cat sprite (Sprite1) before adding your own:

playwright-cli run-code "$(cat <<'EOF'
async page => await page.evaluate(() => {
  const vm = window.vm;
  const cat = vm.runtime.targets.find(t => t.sprite.name === 'Sprite1');
  if (cat) vm.deleteSprite(cat.id);
  return 'Default sprite deleted';
})
EOF
)"

Note: This requires the VM to be connected first (see the scratch-project-edit skill for the VM finder code).

Available Sprites Reference

Animal Sprites

Sprite NameNotes
Bat2 costumes
Bear2 costumes
Bear-walkingwalking animation
Beetle2 costumes
Butterfly 12 costumes
Butterfly 22 costumes
Catdefault sprite, 2 costumes
Cat 2alternate cat
Cat Flyingflying animation
Chick3 costumes
Crab2 costumes
Dinosaur1–5various dinosaurs
Dog12 costumes
Dog23 costumes
Dove2 costumes
Dragon2 costumes
Dragonfly2 costumes
Duck2 costumes
Elephant2 costumes
Fish4 costumes
Fox2 costumes
Frog2 costumes
Frog 2alternate frog
Giraffe2 costumes
Grasshopper2 costumes
Hare4 costumes (hare-a through hare-d)
Hedgehog2 costumes
Hen2 costumes
Hippo12 costumes
Horse2 costumes
Jellyfish4 costumes
Ladybug12 costumes
Ladybug24 costumes
Lion2 costumes
Llama3 costumes
Monkey3 costumes
Mouse12 costumes
Octopus5 costumes
Owl2 costumes
Panther3 costumes
Parrot2 costumes
Penguin3 costumes
Penguin 22 costumes
Polar Bear3 costumes
Pufferfish3 costumes
Puppy3 costumes
Rabbit5 costumes
Reindeer2 costumes
Rooster3 costumes
Shark2 costumes
Shark 23 costumes
Snake3 costumes
Squirrel2 costumes
Starfish2 costumes
Toucan2 costumes
Unicorn2 costumes
Unicorn 23 costumes
Unicorn Runningrunning animation
Zebra2 costumes

Commonly Used Non-Animal Sprites

Sprite NameType
Arrow1object
Ballobject
Button1–5UI elements
Green FlagUI element
Heartobject
Keyobject
Lightningeffect
Rocketshipvehicle
Starobject
Sunnature
Tree1nature
Treesnature

Complete Example: Add Hare and Frog for a Story

playwright-cli run-code "$(cat <<'EOF'
async (page) => {
  // Helper: open sprite library via JS click (language-independent)
  const openSpriteLibrary = async () => {
    await page.evaluate(() => {
      const btn = document.querySelector(
        'div[class*="sprite-selector_add-button"] button[class*="action-menu_main-button"]'
      );
      if (btn) btn.click();
    });
    await page.waitForTimeout(2000);
  };

  // Helper: select a sprite by English name from the open library dialog
  const selectSprite = async (name) => {
    await page.evaluate((spriteName) => {
      const spans = document.querySelectorAll('span[class*="library-item_library-item-name"]');
      for (const span of spans) {
        if (span.textContent.trim() === spriteName) {
          span.closest('button[class*="library-item_library-item"]').click();
          return;
        }
      }
      throw new Error('Sprite not found: ' + spriteName);
    }, name);
    await page.waitForTimeout(1000);
  };

  // Delete default cat sprite (requires VM to be connected)
  await page.evaluate(() => {
    const vm = window.vm;
    const cat = vm.runtime.targets.find(t => t.sprite.name === 'Sprite1');
    if (cat) vm.deleteSprite(cat.id);
  });

  // Add Hare
  await openSpriteLibrary();
  await selectSprite('Hare');

  // Add Frog
  await openSpriteLibrary();
  await selectSprite('Frog');

  // Rename sprites
  await page.evaluate(() => {
    const vm = window.vm;
    const hare = vm.runtime.targets.find(t => t.sprite.name === 'Hare');
    if (hare) vm.renameSprite(hare.id, 'Rabbit');
    const frog = vm.runtime.targets.find(t => t.sprite.name === 'Frog');
    if (frog) vm.renameSprite(frog.id, 'Turtle');
  });

  return 'Added and renamed Hare → Rabbit, Frog → Turtle';
}
EOF
)"

Tips & Troubleshooting

Dialog Not Opening

  • The sprite chooser button has nested sub-buttons (upload, surprise, paint, library) that intercept clicks. Always use the JavaScript click() pattern with the CSS class selector shown above.
  • If the dialog still doesn't open, verify the selector matches by checking document.querySelector('div[class*="sprite-selector_add-button"] button[class*="action-menu_main-button"]') returns a non-null element.

Sprite Not Found in Search

  • All sprite names are in English regardless of the editor locale. Always search with English names (e.g., "Hare", "Cat", "Dog").
  • The search input matches on sprite names. If no results appear, clear the search and browse by category instead.

Adding Multiple Sprites Quickly

  • The library dialog closes after each selection. You must re-open it for each sprite.
  • For batch additions, use the playwright-cli run-code pattern with helper functions (see complete example above).

Sprite Position After Adding

  • Newly added sprites appear at a default position (often near center or slightly offset).
  • Use vm.runtime.targets.find(t => t.sprite.name === 'Name') to find the target, then set .x, .y, .size, .direction properties, or use motion blocks in your program to position sprites at startup.

CSS Class Hash Changes

  • The hash suffix in CSS class names (e.g., _KILTP in action-menu_main-button_KILTP) may change when Scratch deploys a new build. The prefix portion (action-menu_main-button) is stable. Always use [class*="prefix"] matching, never exact class names.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,790. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.