mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 06:51:16 +08:00
Generates a full dedicated Docusaurus page for every one of the 132 skills
(73 bundled + 59 optional) under website/docs/user-guide/skills/{bundled,optional}/<category>/.
Each page carries the skill's description, metadata (version, author, license,
dependencies, platform gating, tags, related skills cross-linked to their own
pages), and the complete SKILL.md body that Hermes loads at runtime.
Previously the two catalog pages just listed skills with a one-line blurb and
no way to see what the skill actually did — users had to go read the source
repo. Now every skill has a browsable, searchable, cross-linked reference in
the docs.
- website/scripts/generate-skill-docs.py — generator that reads skills/ and
optional-skills/, writes per-skill pages, regenerates both catalog indexes,
and rewrites the Skills section of sidebars.ts. Handles MDX escaping
(outside fenced code blocks: curly braces, unsafe HTML-ish tags) and
rewrites relative references/*.md links to point at the GitHub source.
- website/docs/reference/skills-catalog.md — regenerated; each row links to
the new dedicated page.
- website/docs/reference/optional-skills-catalog.md — same.
- website/sidebars.ts — Skills section now has Bundled / Optional subtrees
with one nested category per skill folder.
- .github/workflows/{docs-site-checks,deploy-site}.yml — run the generator
before docusaurus build so CI stays in sync with the source SKILL.md files.
Build verified locally with `npx docusaurus build`. Only remaining warnings
are pre-existing broken link/anchor issues in unrelated pages.
233 lines
8.1 KiB
Markdown
233 lines
8.1 KiB
Markdown
---
|
|
title: "Pixel Art — Convert images into retro pixel art with hardware-accurate palettes (NES, Game Boy, PICO-8, C64, etc"
|
|
sidebar_label: "Pixel Art"
|
|
description: "Convert images into retro pixel art with hardware-accurate palettes (NES, Game Boy, PICO-8, C64, etc"
|
|
---
|
|
|
|
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
|
|
|
# Pixel Art
|
|
|
|
Convert images into retro pixel art with hardware-accurate palettes (NES, Game Boy, PICO-8, C64, etc.), and animate them into short videos. Presets cover arcade, SNES, and 10+ era-correct looks. Use `clarify` to let the user pick a style before generating.
|
|
|
|
## Skill metadata
|
|
|
|
| | |
|
|
|---|---|
|
|
| Source | Bundled (installed by default) |
|
|
| Path | `skills/creative/pixel-art` |
|
|
| Version | `2.0.0` |
|
|
| Author | dodo-reach |
|
|
| License | MIT |
|
|
| Tags | `creative`, `pixel-art`, `arcade`, `snes`, `nes`, `gameboy`, `retro`, `image`, `video` |
|
|
|
|
## Reference: full SKILL.md
|
|
|
|
:::info
|
|
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
|
:::
|
|
|
|
# Pixel Art
|
|
|
|
Convert any image into retro pixel art, then optionally animate it into a short
|
|
MP4 or GIF with era-appropriate effects (rain, fireflies, snow, embers).
|
|
|
|
Two scripts ship with this skill:
|
|
|
|
- `scripts/pixel_art.py` — photo → pixel-art PNG (Floyd-Steinberg dithering)
|
|
- `scripts/pixel_art_video.py` — pixel-art PNG → animated MP4 (+ optional GIF)
|
|
|
|
Each is importable or runnable directly. Presets snap to hardware palettes
|
|
when you want era-accurate colors (NES, Game Boy, PICO-8, etc.), or use
|
|
adaptive N-color quantization for arcade/SNES-style looks.
|
|
|
|
## When to Use
|
|
|
|
- User wants retro pixel art from a source image
|
|
- User asks for NES / Game Boy / PICO-8 / C64 / arcade / SNES styling
|
|
- User wants a short looping animation (rain scene, night sky, snow, etc.)
|
|
- Posters, album covers, social posts, sprites, characters, avatars
|
|
|
|
## Workflow
|
|
|
|
Before generating, confirm the style with the user. Different presets produce
|
|
very different outputs and regenerating is costly.
|
|
|
|
### Step 1 — Offer a style
|
|
|
|
Call `clarify` with 4 representative presets. Pick the set based on what the
|
|
user asked for — don't just dump all 14.
|
|
|
|
Default menu when the user's intent is unclear:
|
|
|
|
```python
|
|
clarify(
|
|
question="Which pixel-art style do you want?",
|
|
choices=[
|
|
"arcade — bold, chunky 80s cabinet feel (16 colors, 8px)",
|
|
"nes — Nintendo 8-bit hardware palette (54 colors, 8px)",
|
|
"gameboy — 4-shade green Game Boy DMG",
|
|
"snes — cleaner 16-bit look (32 colors, 4px)",
|
|
],
|
|
)
|
|
```
|
|
|
|
When the user already named an era (e.g. "80s arcade", "Gameboy"), skip
|
|
`clarify` and use the matching preset directly.
|
|
|
|
### Step 2 — Offer animation (optional)
|
|
|
|
If the user asked for a video/GIF, or the output might benefit from motion,
|
|
ask which scene:
|
|
|
|
```python
|
|
clarify(
|
|
question="Want to animate it? Pick a scene or skip.",
|
|
choices=[
|
|
"night — stars + fireflies + leaves",
|
|
"urban — rain + neon pulse",
|
|
"snow — falling snowflakes",
|
|
"skip — just the image",
|
|
],
|
|
)
|
|
```
|
|
|
|
Do NOT call `clarify` more than twice in a row. One for style, one for scene if
|
|
animation is on the table. If the user explicitly asked for a specific style
|
|
and scene in their message, skip `clarify` entirely.
|
|
|
|
### Step 3 — Generate
|
|
|
|
Run `pixel_art()` first; if animation was requested, chain into
|
|
`pixel_art_video()` on the result.
|
|
|
|
## Preset Catalog
|
|
|
|
| Preset | Era | Palette | Block | Best for |
|
|
|--------|-----|---------|-------|----------|
|
|
| `arcade` | 80s arcade | adaptive 16 | 8px | Bold posters, hero art |
|
|
| `snes` | 16-bit | adaptive 32 | 4px | Characters, detailed scenes |
|
|
| `nes` | 8-bit | NES (54) | 8px | True NES look |
|
|
| `gameboy` | DMG handheld | 4 green shades | 8px | Monochrome Game Boy |
|
|
| `gameboy_pocket` | Pocket handheld | 4 grey shades | 8px | Mono GB Pocket |
|
|
| `pico8` | PICO-8 | 16 fixed | 6px | Fantasy-console look |
|
|
| `c64` | Commodore 64 | 16 fixed | 8px | 8-bit home computer |
|
|
| `apple2` | Apple II hi-res | 6 fixed | 10px | Extreme retro, 6 colors |
|
|
| `teletext` | BBC Teletext | 8 pure | 10px | Chunky primary colors |
|
|
| `mspaint` | Windows MS Paint | 24 fixed | 8px | Nostalgic desktop |
|
|
| `mono_green` | CRT phosphor | 2 green | 6px | Terminal/CRT aesthetic |
|
|
| `mono_amber` | CRT amber | 2 amber | 6px | Amber monitor look |
|
|
| `neon` | Cyberpunk | 10 neons | 6px | Vaporwave/cyber |
|
|
| `pastel` | Soft pastel | 10 pastels | 6px | Kawaii / gentle |
|
|
|
|
Named palettes live in `scripts/palettes.py` (see `references/palettes.md` for
|
|
the complete list — 28 named palettes total). Any preset can be overridden:
|
|
|
|
```python
|
|
pixel_art("in.png", "out.png", preset="snes", palette="PICO_8", block=6)
|
|
```
|
|
|
|
## Scene Catalog (for video)
|
|
|
|
| Scene | Effects |
|
|
|-------|---------|
|
|
| `night` | Twinkling stars + fireflies + drifting leaves |
|
|
| `dusk` | Fireflies + sparkles |
|
|
| `tavern` | Dust motes + warm sparkles |
|
|
| `indoor` | Dust motes |
|
|
| `urban` | Rain + neon pulse |
|
|
| `nature` | Leaves + fireflies |
|
|
| `magic` | Sparkles + fireflies |
|
|
| `storm` | Rain + lightning |
|
|
| `underwater` | Bubbles + light sparkles |
|
|
| `fire` | Embers + sparkles |
|
|
| `snow` | Snowflakes + sparkles |
|
|
| `desert` | Heat shimmer + dust |
|
|
|
|
## Invocation Patterns
|
|
|
|
### Python (import)
|
|
|
|
```python
|
|
import sys
|
|
sys.path.insert(0, "/home/teknium/.hermes/skills/creative/pixel-art/scripts")
|
|
from pixel_art import pixel_art
|
|
from pixel_art_video import pixel_art_video
|
|
|
|
# 1. Convert to pixel art
|
|
pixel_art("/path/to/photo.jpg", "/tmp/pixel.png", preset="nes")
|
|
|
|
# 2. Animate (optional)
|
|
pixel_art_video(
|
|
"/tmp/pixel.png",
|
|
"/tmp/pixel.mp4",
|
|
scene="night",
|
|
duration=6,
|
|
fps=15,
|
|
seed=42,
|
|
export_gif=True,
|
|
)
|
|
```
|
|
|
|
### CLI
|
|
|
|
```bash
|
|
cd /home/teknium/.hermes/skills/creative/pixel-art/scripts
|
|
|
|
python pixel_art.py in.jpg out.png --preset gameboy
|
|
python pixel_art.py in.jpg out.png --preset snes --palette PICO_8 --block 6
|
|
|
|
python pixel_art_video.py out.png out.mp4 --scene night --duration 6 --gif
|
|
```
|
|
|
|
## Pipeline Rationale
|
|
|
|
**Pixel conversion:**
|
|
1. Boost contrast/color/sharpness (stronger for smaller palettes)
|
|
2. Posterize to simplify tonal regions before quantization
|
|
3. Downscale by `block` with `Image.NEAREST` (hard pixels, no interpolation)
|
|
4. Quantize with Floyd-Steinberg dithering — against either an adaptive
|
|
N-color palette OR a named hardware palette
|
|
5. Upscale back with `Image.NEAREST`
|
|
|
|
Quantizing AFTER downscale keeps dithering aligned with the final pixel grid.
|
|
Quantizing before would waste error-diffusion on detail that disappears.
|
|
|
|
**Video overlay:**
|
|
- Copies the base frame each tick (static background)
|
|
- Overlays stateless-per-frame particle draws (one function per effect)
|
|
- Encodes via ffmpeg `libx264 -pix_fmt yuv420p -crf 18`
|
|
- Optional GIF via `palettegen` + `paletteuse`
|
|
|
|
## Dependencies
|
|
|
|
- Python 3.9+
|
|
- Pillow (`pip install Pillow`)
|
|
- ffmpeg on PATH (only needed for video — Hermes installs package this)
|
|
|
|
## Pitfalls
|
|
|
|
- Pallet keys are case-sensitive (`"NES"`, `"PICO_8"`, `"GAMEBOY_ORIGINAL"`).
|
|
- Very small sources (<100px wide) collapse under 8-10px blocks. Upscale the
|
|
source first if it's tiny.
|
|
- Fractional `block` or `palette` will break quantization — keep them positive ints.
|
|
- Animation particle counts are tuned for ~640x480 canvases. On very large
|
|
images you may want a second pass with a different seed for density.
|
|
- `mono_green` / `mono_amber` force `color=0.0` (desaturate). If you override
|
|
and keep chroma, the 2-color palette can produce stripes on smooth regions.
|
|
- `clarify` loop: call it at most twice per turn (style, then scene). Don't
|
|
pepper the user with more picks.
|
|
|
|
## Verification
|
|
|
|
- PNG is created at the output path
|
|
- Clear square pixel blocks visible at the preset's block size
|
|
- Color count matches preset (eyeball the image or run `Image.open(p).getcolors()`)
|
|
- Video is a valid MP4 (`ffprobe` can open it) with non-zero size
|
|
|
|
## Attribution
|
|
|
|
Named hardware palettes and the procedural animation loops in `pixel_art_video.py`
|
|
are ported from [pixel-art-studio](https://github.com/Synero/pixel-art-studio)
|
|
(MIT). See `ATTRIBUTION.md` in this skill directory for details.
|