Install
$ agentstack add skill-stevysmith-find-me-a-museum-image-skill-find-me-a-museum-image-skill ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Find me a museum image
Search museum open-access APIs for public-domain (CC0) artwork, preview candidates visually, and download a high-resolution image into the user's project with attribution — all from the CLI.
The tool is scripts/museum_image.py inside this skill's directory — the directory containing this SKILL.md. Since your working directory is the user's project, call it by absolute path; ` below means this skill's directory. Python 3, stdlib only. Museums that work with no API key: artic (Art Institute of Chicago), met (The Met), cleveland (Cleveland Museum of Art), smk (Statens Museum for Kunst, Denmark), rijks (Rijksmuseum), getty (J. Paul Getty Museum). With a free key in an env var: smithsonian (SMITHSONIANAPIKEY`).
Workflow
1. Turn the request into search terms
Distill what the user actually needs:
- Subject/mood: "calm sea", "sunflowers", "storm", "city at night". Museum search is keyword-based — search concrete nouns and artist names, not vibes. Translate "something serene for a meditation app" into searches like
"calm sea","water lilies","quiet landscape", or artist names (monet,hammershoi,hiroshige). - Orientation: a hero/banner wants
--orientation landscape; a mobile splash wantsportrait. - Usage context: where in the project will it go? This decides the output path and how picky to be about palette.
Run 2–4 different queries rather than one — museum metadata is sparse, and synonyms surface different works.
2. Search with thumbnails
python3 /scripts/museum_image.py search "water lilies" \
--orientation landscape --limit 6 \
--save /results.json --thumbs /thumbs
Replace ` with your session's scratchpad directory (or any temp dir) — these are working files, not project files. --limit is per museum, so --limit 6 can return ~35 results across the six keyless museums; 4–6 is a good range. Give each query its own files (results2.json, thumbs2/) — thumbnail names restart at 00 every run, so reusing a thumbs dir mixes artworks from different queries. Results are numbered; thumbnails land as NNmuseum.jpg`.
3. Curate visually — this is the key step
Read the downloaded thumbnail images (the Read tool renders them). Judge them against the user's actual need: palette, mood, composition, whether text would overlay legibly. Metadata cannot tell you a painting is muddy brown; your eyes can. Discard weak candidates and, if nothing sings, run another query with different terms before settling.
4. Present a shortlist
Show the user the best 2–4 candidates: title, artist, date, museum, dimensions, and the museum page URL. If the user asked you to just pick one, pick the best match and say why.
5. Download at full resolution
python3 /scripts/museum_image.py download /results.json 3 \
--out assets/hero.jpg
This fetches the highest practical resolution (Cleveland's multi-hundred-MB native TIFF is deliberately skipped; its URL is in the results JSON as full_tiff_url if anyone truly wants it) and writes an *.attribution.json sidecar next to it (title, artist, museum, license, source URL). Put the image where the project keeps static assets (public/, assets/, static/ — check first). Full-res museum scans can be 5–50 MB; if the project needs a smaller file, resize a copy (e.g. sips -Z 2400 out.jpg on macOS) but keep the sidecar accurate.
6. Attribution
CC0/public-domain images require no credit, but crediting is good practice. Offer the user the suggested credit line the download prints, e.g.:
> Claude Monet, "Low Tide at Pourville" (1882). The Cleveland Museum of Art. Public Domain (CC0).
If the image goes on a public page, suggest a caption or an HTML comment near the asset reference.
Sharp edges
- Trust the license field, not assumptions. The script already filters to public-domain/CC0 works, but if you fetch museum data by hand, check the rights field before using an image — most museums also serve copyrighted works through the same APIs.
- The Met search is the slowest (it needs one request per candidate object), and its image index is stale — a search can return hits whose objects turn out non-PD or imageless, so Met sometimes contributes fewer results than other museums. Normal, not a bug.
- If a museum errors or times out, the search continues without it — warnings go to stderr. Don't treat a single museum failure as a task failure.
--orientationfilters on known dimensions: artic, cleveland, smk, rijks, and getty report real pixel dims; met uses the artwork's physical proportions as a proxy; smithsonian rows pass through unfiltered. A stderr note tells you how many results dodged the filter — confirm those from their thumbnails.- Jurisdiction caveat: museum public-domain labels follow US rules (published before ~1930). A 1929 Picasso etching can be CC0 at a US museum yet still copyrighted in life+70 countries. For a user shipping to an international audience, prefer artists who died 70+ years ago — when in doubt, mention it.
- Empty results usually mean the query is too specific. Broaden it ("impressionist coast" → "coast"), try an artist name, or drop
--orientation(works with unknown dimensions are never filtered out, but known-wrong ones are). - Rijksmuseum has no free-text search — the script queries its
creatorandtitlefields, so subject words work poorly there; artist names work well. Titles come back in Dutch. - SMK's search is fuzzy: "monet" matches the Danish island "Møn" (SMK owns no Monet). Judge SMK hits by their thumbnails, not by faith in the keyword match.
- Getty search results omit medium/dimensions — that's why those columns are sometimes blank for
gettyrows. - Smithsonian needs a free instant key from https://api.data.gov/signup/ (
SMITHSONIAN_API_KEY). Only mention it if the user wants that collection; six museums already work with no key. - More API detail (endpoints, field maps, image URL recipes, verified gotchas) lives in
references/apis.mdif you need to query a museum directly — including a recipe for National Gallery of Art, which has no live search API but does have an open IIIF server.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: stevysmith
- Source: stevysmith/find-me-a-museum-image-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.