Meme Generation Skill for Hermes Agent: Template PNGs with Pillow
Create meme PNGs from templates with Pillow text overlay.
Written by Neura Market from the official Hermes Agent documentation for Meme Generation. Commands, paths, and version numbers are reproduced from the source unchanged.
Read the official documentationThe Meme Generation skill lets Hermes Agent turn a topic into an actual meme image: it selects a template, writes short captions, and renders a real .png with text overlaid using Pillow. Reach for it when a user asks for a meme, wants a joke about a specific frustration or situation, or says something like "meme this". It is an optional creative skill, so it is installed on demand rather than shipping with the base runtime.
What it does
The skill wraps a Python script that does two jobs. First, it resolves a template: either one of ten curated layouts with hand-tuned text positioning, or any of the roughly one hundred popular imgflip templates by name or ID. Second, it draws the captions onto the template image and writes a .png to a path you choose. The result is a file you can hand back to the user through the agent's media delivery mechanism.
Because the script handles the rendering, the agent's job is mostly editorial: read the request, identify the joke structure, pick the template that matches that structure, and write captions short enough to look right. The skill is authored by adanaleycio, version 2.0.0, MIT licensed, and runs on linux, macos, and windows.
Before you start
This is an optional-tier skill, so it is not present until it is installed. The skill path is optional-skills/creative/meme-generation. You need Python available to run the generator script, and the script needs Pillow for the text overlay work. The source does not list any other install steps, so treat the skill's own install as the prerequisite and do not assume extra packages.
One practical detail: the script caches template images in scripts/.cache/ after the first download. That means the first run for a given template depends on fetching it, and later runs reuse the cached copy. If you are working offline or behind a restrictive network, plan for that first fetch.
Template options
Curated templates
Ten templates ship with custom text placement, which means the captions sit where the joke expects them. Each has a fixed set of fields, and you must supply captions in that field order.
| ID | Name | Fields | Best for |
|---|---|---|---|
this-is-fine | This is Fine | top, bottom | chaos, denial |
drake | Drake Hotline Bling | reject, approve | rejecting/preferring |
distracted-boyfriend | Distracted Boyfriend | distraction, current, person | temptation, shifting priorities |
two-buttons | Two Buttons | left, right, person | impossible choice |
expanding-brain | Expanding Brain | 4 levels | escalating irony |
change-my-mind | Change My Mind | statement | hot takes |
woman-yelling-at-cat | Woman Yelling at Cat | woman, cat | arguments |
one-does-not-simply | One Does Not Simply | top, bottom | deceptively hard things |
grus-plan | Gru's Plan | step1-3, realization | plans that backfire |
batman-slapping-robin | Batman Slapping Robin | robin, batman | shutting down bad ideas |
Dynamic templates
Anything outside the curated list can still be used by name or imgflip ID. These get smart default positioning: top and bottom for two-field templates, evenly spaced for three or more. To find one, search the template catalogue:
python "$SKILL_DIR/scripts/generate_meme.py" --search "disaster"
Use the search when the topic suggests a visual the curated ten do not cover. It is also the right move when you know the meme by name but not its ID.
Generating a classic template meme
This is the default path and the one most requests will take.
- Read the request and name the core dynamic: chaos, a dilemma, a preference, irony, a bad plan.
- Choose the template whose "Best for" description matches that dynamic, or search with
--searchif none of the curated ten fit. - Write captions for each field. Keep each one to 8-12 words at most; shorter is better.
- Locate the skill's script directory:
SKILL_DIR=$(dirname "$(find ~/.hermes/skills -path '*/meme-generation/SKILL.md' 2>/dev/null | head -1)")
- Run the generator with the template ID, an output path, and one caption per field:
python "$SKILL_DIR/scripts/generate_meme.py" <template_id> ~/.hermes/cache/scratch/meme.png "caption 1" "caption 2" ...
- Return the image with
MEDIA:~/.hermes/cache/scratch/meme.png.
The field count matters. A two-field template takes two captions; expanding-brain takes four; grus-plan takes four as well (three steps plus the realization). Passing the wrong number is the most common way a run goes wrong, so check the table before you write the command.
Generating a custom AI image meme
When no classic template fits, or the user wants something original, the skill can overlay text on an image you generate first. This path needs image_generate to be available.
-
Write the captions before you generate anything. The joke drives the scene, not the other way around.
-
Use
image_generateto create a scene matching the concept. Do not put text in the image prompt; the script adds text afterwards. Describe only the visual scene. -
Get the generated image path from the
image_generateresult URL, downloading it locally if needed. -
Run the script with
--imageto overlay text. There are two modes.Overlay puts text directly on the image, white with a black outline:
python "$SKILL_DIR/scripts/generate_meme.py" --image /path/to/scene.png ~/.hermes/cache/scratch/meme.png "top text" "bottom text"
Bars puts black bars above and below the image with white text, which is cleaner and always readable:
python "$SKILL_DIR/scripts/generate_meme.py" --image /path/to/scene.png --bars ~/.hermes/cache/scratch/meme.png "top text" "bottom text"
Choose --bars when the scene is busy or detailed and overlaid text would be hard to read.
- If
vision_analyzeis available, check the result before delivering it:
vision_analyze(image_url="~/.hermes/cache/scratch/meme.png", question="Is the text legible and well-positioned? Does the meme work visually?")
If the vision model reports problems such as unreadable text or poor placement, switch modes (overlay to bars or back) or regenerate the scene.
- Return the image with
MEDIA:~/.hermes/cache/scratch/meme.png.
Worked examples
These show the caption style the skill expects: short, punchy, matched to the template's structure.
"debugging production at 2 AM":
python generate_meme.py this-is-fine ~/.hermes/cache/scratch/meme.png "SERVERS ARE ON FIRE" "This is fine"
"choosing between sleep and one more episode":
python generate_meme.py drake ~/.hermes/cache/scratch/meme.png "Getting 8 hours of sleep" "One more episode at 3 AM"
"the stages of a Monday morning":
python generate_meme.py expanding-brain ~/.hermes/cache/scratch/meme.png "Setting an alarm" "Setting 5 alarms" "Sleeping through all alarms" "Working from bed"
Notice that the drake example has two captions (reject, approve) and the expanding-brain example has four, one per level. That is the field-count rule in action.
Listing templates
To see every template the script knows about:
python generate_meme.py --list
Run this when you are unsure whether a template name is recognised, or when you want to browse before choosing.
When not to use it
The source does not name a direct alternative for this task, but it does point at a related skill: ascii-art. If the request is for text-based visual output rather than a rendered image, that is the neighbouring option. For anything that needs a real .png with captions on a photographic or illustrated template, this skill is the one to use.
Limits and gotchas
The source is explicit about what makes a meme fail:
- Keep captions short. Long text looks terrible on a meme.
- Match the number of text arguments to the template's field count.
- Pick the template that fits the joke structure, not just the topic. A topic can map to several templates; the structure is what decides.
- Do not generate hateful, abusive, or personally targeted content.
- Template images are cached in
scripts/.cache/after the first download, so the first use of a template is the one that fetches.
Verifying the result
The output is correct when all of these hold:
- A .png file exists at the output path.
- The text is legible, white with a black outline, on the template.
- The joke lands: the caption matches the template's intended structure.
- The file can be delivered through the
MEDIA:path.
If any of those fail, the fix is usually editorial (shorter captions, a different template) rather than technical.
What pairs with it
The source lists ascii-art as a related skill. Both are creative-output skills, and ascii-art covers the case where the user wants something visual but text-based. Beyond that, the custom-image path depends on image_generate and optionally vision_analyze, so those capabilities are the natural companions when you want original scenes rather than stock templates.