stock-imagesSAFE
Claude Code skill for searching and downloading stock images from Pexels, Unsplash, and Pixabay
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
An Agent Skill for searching and downloading stock images from Pexels, Unsplash, and Pixabay.
Works with Claude Code, Codex, and other agents supported by the npx skills CLI.
Features
- Search stock images across multiple providers simultaneously
- Download images directly to your project
- Smart orientation detection (hero → landscape, avatar → portrait)
- Secure API key storage (
~/.config/stock-images/keys.jsonwithchmod 600) - Attribution reminders for TOS compliance
Installation
npx skills@latest add jeanpfs/stock-images --all -y -g
Install for Claude Code only:
npx skills@latest add jeanpfs/stock-images --skill stock-images -a claude-code -g -y
Install for Codex only:
npx skills@latest add jeanpfs/stock-images --skill stock-images -a codex -g -y
Setup
After installing, you need API keys from at least one provider (all free):
- Pexels: https://www.pexels.com/api/
- Unsplash: https://unsplash.com/developers
- Pixabay: https://pixabay.com/api/docs/
See SETUP.md for detailed instructions.
Usage Examples
- "Find stock photos of mountains for the hero section"
- "I need a professional headshot placeholder for this profile card"
- "Search for food photography on Unsplash"
- "Download image #3 to ./public/images"
Security
- API keys stored with
chmod 600(owner-only access) - Keys never displayed in Claude's output
- Downloads restricted to known stock image provider domains
- HTTPS enforced on all connections
- File size validation on downloads
Contributing
See CONTRIBUTING.md. Please follow the Code of Conduct. Changes are tracked in CHANGELOG.md.
For vulnerabilities, use GitHub's "Report a vulnerability" as described in SECURITY.md.
License
MIT
1c6c3d9a3154OBSERVED · 2026-10-14Host compatibility
What the documentation claims. We have not run a compatibility test.
| Host | Status | Notes |
|---|---|---|
| claude-code | mentioned | |
| codex | mentioned |
What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
name: stock-images
description: Search and download stock photos from Pexels, Unsplash, and Pixabay for projects, landing pages, UI mockups, and content. Use when users explicitly ask to find stock photos, need a hero/profile/content image, or want to download a selected stock image.
---
## Security Rules
- NEVER display API keys in your output
- NEVER echo full curl commands that contain API keys
- **Pixabay limitation**: Pixabay requires the API key as a URL query parameter, which is visible in process lists (`ps aux`). Be aware of this inherent API limitation. Never display the full Pixabay curl command in output.
- Only download from allowed domains:
- `images.pexels.com`
- `images.unsplash.com`, `plus.unsplash.com`
- `pixabay.com`, `cdn.pixabay.com`
- All URLs MUST use HTTPS
- After downloading, check file size — alert if > 10MB
- For Unsplash downloads, use the `links.download` URL (not `urls.raw`) to comply with Unsplash API TOS (triggers download count)
## Non-Activation
Do NOT activate this skill when:
- Discussing image components (`<img>`, `next/image`, etc.)
- AI image generation is requested (that is a different skill)
- Referencing existing images already in the project
## Setup Detection
Before searching, check if API keys are configured:
```bash
test -f ~/.config/stock-images/keys.json && stat -f "%Lp" ~/.config/stock-images/keys.json 2>/dev/null || stat -c "%a" ~/.config/stock-images/keys.json 2>/dev/null
```
- If the file does not exist: guide the user interactively through setup:
1. Ask which providers they want to use (Pexels, Unsplash, Pixabay — all free)
2. Provide the relevant signup links:
- Pexels: https://www.pexels.com/api/
- Unsplash: https://unsplash.com/developers
- Pixabay: https://pixabay.com/api/docs/
3. Once the user provides their keys, create the config file via Bash with `chmod 600`
4. NEVER display the keys back after saving
- If permissions are not `600`: warn the user and offer to fix with `chmod 600 ~/.config/stock-images/keys.json`.
- If the file exists with correct permissions: use the keys silently. Do NOT display the file contents, the keys, or commands containing key values.
Determine configured providers without printing secret values:
```bash
python3 - <<'PY'
import json
from pathlib import Path
config = Path.home() / ".config" / "stock-images" / "keys.json"
data = json.loads(config.read_text())
providers = [
name for name in ("pexels", "unsplash", "pixabay")
if data.get(name) and not str(data[name]).startswith("YOUR_")
]
print("\n".join(providers))
PY
```
Parse the JSON to determine which providers are configured (have non-empty, non-placeholder values). At least one provider is required.
## Search Implementation
Extract from the user's request:
- **query**: what to search for (required)
- **count**: how many images (default: 5, max: 20)
- **orientation**: landscape, portrait, or square — infer from context (e.g., "hero banner" → landscape, "profile photo" → portrait)
- **provider**: specific provider or "all" (default: all configured)
Keep the parsed search results and metadata available for follow-up requests in the same conversation. If the user later says "download image #3", map that number back to the exact provider, image URL, download URL, author, author profile, and attribution data from the presented results.
Run curl commands for each configured provider. When multiple providers are configured, run them in parallel (separate Bash tool calls).
### Pexels
```bash
curl -sS -G --max-time 15 --fail "https://api.pexels.com/v1/search" \
--data-urlencode "query=SEARCH_QUERY" \
-d "per_page=COUNT" \
-d "orientation=ORIENTATION" \
-H "Authorization: PEXELS_KEY"
```
Response fields:
- `photos[].src.original` — full image URL
- `photos[].src.medium` — thumbnail
- `photos[].photographer` — author name
- `photos[].photographer_url` — author profile
- `photos[].width`, `photos[].height` — dimensions
### Unsplash
```bash
curl -sS -G --max-time 15 --fail "https://api.unsplash.com/search/photos" \
--data-urlencode "query=SEARCH_QUERY" \
-d "per_page=COUNT" \
-d "orientation=ORIENTATION" \
-H "Authorization: Client-ID UNSPLASH_KEY"
```
Response fields:
- `results[].urls.raw` — full image URL
- `results[].urls.small` — thumbnail
- `results[].user.name` — author name
- `results[].user.links.html` — author profile
- `results[].links.download` — download URL (use this for downloads, not urls.raw)
- `results[].width`, `results[].height` — dimensions
### Pixabay
```bash
curl -sS -G --max-time 15 --fail "https://pixabay.com/api/" \
-d "key=PIXABAY_KEY" \
--data-urlencode "q=SEARCH_QUERY" \
-d "per_page=COUNT" \
-d "orientation=ORIENTATION" \
-d "image_type=photo"
```
Pixabay-specific: map "landscape" → "horizontal", "portrait" → "vertical". Minimum per_page is 3.
Response fields:
- `hits[].largeImageURL` — full image URL
- `hits[].previewURL` — thumbnail
- `hits[].user` — author name
- `hits[].user_id` — for building profile URL: `https://pixabay.com/users/USER-USER_ID/`
- `hits[].imageWidth`, `hits[].imageHeight` — dimensions
- `hits[].tags` — description
### Error Handling
- **curl exits non-zero / timeout**: skip that provider, continue with others, inform user
- **HTTP 401**: API key invalid or revoked — inform user, suggest re-running setup
- **HTTP 429**: rate limit — inform user, suggest waiting or trying another provider
- **Empty / malformed JSON**: skip provider, continue with others
- **Malformed keys.json**: inform user config is corrupted, offer to recreate
### Presenting Results
Present results in the user's language. Format:
```
## Results for "query" (N images)
### Provider Name
1. "Image Title/Description" — by [Author Name](author_profile_url)
URL: https://...
Resolution: WxH
```
After presenting, ask if the user wants to download any of them.
## Download Implementation
When the user selects an image to download:
1. **Validate thTrust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (0)
No findings outside the package's declared scope.
Gates applied: no_behavioural_pass.
1c6c3d9a3154full audit observations/trust-audit/skill/jeanpfs__stock-images.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-14 | 1c6c3d9a3154 | SAFE | B | 89 | first audit |
Questions
What does the stock-images skill do?
Claude Code skill for searching and downloading stock images from Pexels, Unsplash, and Pixabay
Is stock-images safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can stock-images access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
Which assistants does stock-images work with?
Its documentation mentions claude-code and codex. That is what the text claims, not a compatibility test we ran.
How current is this page?
The grade is for one exact copy of the source (1c6c3d9a3154), read on 2026-10-14. The repository is watched, and a new audit runs when it changes — this is the first audit.