A tiny zero-dependency CLI for generating memes via the free memegen.link API. Agent-friendly.
Project description
meme — a meme CLI your coding agent can drive
A tiny, zero-dependency meme generator built for coding agents and CI. It ships a bundled Claude Code skill, so you can just say "drop a 'this is fine' meme on the PR" and the agent runs it — and a copy-paste GitHub Action that memes your build status. No API key, no signup, stdlib-only (wraps the free memegen.link API).
Let your agent meme. Install once, and Claude Code / Codex drive it for you:
you: make a "this is fine" meme about prod being down
agent: $ meme -t fine "prod is down" "this is fine" --print-url
→ https://api.memegen.link/images/fine/prod_is_down/this_is_fine.png
Meme your CI. A this is fine meme on every red build — copy-paste workflow
in examples/pr-meme.yml:
url=$(meme -t fine "tests failed" "this is fine" --print-url)
gh pr comment "$PR" --body ""
It's a normal CLI too — meme drake "manual deploys" "ci/cd" works from any
terminal. See Usage.
Install
Requires Python 3.8+. Easiest is uv (installs
the meme command in its own isolated environment):
uv tool install makememe # or: pipx install makememe
Update later with:
uv tool upgrade makememe
Run once without installing anything:
uvx --from makememe meme drake "a" "b"
(If you specifically want pip: python3 -m pip install makememe.)
Check the version anytime:
meme --version
Usage
meme <template> "top line" "bottom line" [-o out.png]
| Flag | Meaning |
|---|---|
-t, --template |
template id as a flag (alternative to the positional). Agents should use this so a single permission approval covers every template |
-o, --out |
output file (default: a unique file in a temp folder, so it never writes into your current directory) |
--bg URL |
use a custom background image instead of a template |
--ext |
png (default), jpg, webp, or gif |
--style / --font |
template style variant / font override |
--open |
open the finished image in your default viewer |
--print-url |
print the image URL, don't download |
--json |
machine-readable output (for scripts/agents) |
--list |
list available template ids |
Examples
meme drake "manual deploys" "ci/cd"
meme same "after I sold" "if I held" "same picture"
meme --bg https://example.com/pic.png "_" "DODGED"
meme regret "SOLD @ 620" "NOW 780 (+26%)" --print-url
meme --list
meme --list --json
Integrations
For sharing (CI, chat, comments) you usually want the public URL, not a
local file — --print-url returns a permanent memegen.link URL you can embed
anywhere with . No download, no image hosting.
- GitHub Actions → PR comment: ready-to-copy workflow at
examples/pr-meme.yml— comments a success/“this is fine” meme on each PR based on whether tests passed. - Slack/Discord: post the URL to a channel; it auto-unfurls into a preview.
url=$(meme -t success "build" "passed" --print-url) # -> public URL, embed it anywhere
Text that starts with -
If a caption line begins with - (e.g. "-26%"), put -- before your lines so
it isn't parsed as a flag:
meme regret --json -- "-26%" "WHY"
(Put flags like --json/-o before the --.)
For agents (Claude Code / Codex / scripts)
The tool is designed to be parsed:
-
Plain mode prints only the output path to stdout (status goes to stderr), so
path=$(meme drake "a" "b")just works. -
--jsonmode prints a single JSON object:{ "path": "/tmp/makememe/meme-ab12cd.png", "bytes": 12345, "url": "https://api.memegen.link/..." }
--list --jsonreturns the template catalog as JSON;--print-url --jsonreturns{"url": "..."}; failures return{"error": "...", "url": "..."}with a non-zero exit code.
Typical agent flow:
meme --list --json # discover template ids
meme drake "old way" "new way" --json # generate, capture the path
Claude Code skill
The package bundles a Claude Code skill. After installing, run one command to make Claude Code auto-discover the tool:
meme --install-skill # installs into ~/.claude/skills/meme/ (all projects)
meme --install-skill --project # or into ./.claude/skills/meme/ (this repo only)
Restart Claude Code, then just ask things like "make a drake meme about
writing tests" and it will call meme for you.
(Other agents like Codex don't use this skill format — they discover everything
through meme --help and meme --list, which already works out of the box.)
Robustness
The CLI is built to fail gracefully, never with a raw traceback:
- Network errors, dead hosts, bad template ids (404), oversized text (414), and non-image backgrounds (415) all exit non-zero with a one-line message — and no partial/garbage file is written.
Ctrl-Cexits cleanly (code 130); piping intoheadetc. won't spew aBrokenPipeError.- Arbitrary text — emoji, CJK,
% # & / ? " \, tabs, control chars, 10k-char lines — is escaped safely.
Run the test suite (stdlib only, no network needed):
python -m unittest discover -s tests
How it works
It builds a memegen.link URL from your template + text (handling all the fiddly
path-segment escaping — spaces, _, -, ?, /, %, etc.), downloads the
image, and saves it. That's the whole trick.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file makememe-0.1.9.tar.gz.
File metadata
- Download URL: makememe-0.1.9.tar.gz
- Upload date:
- Size: 13.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75eff6fb848ee7641d786f7e76437c7b753f7063d8bf8e153b79a437e1553931
|
|
| MD5 |
0cf3d1f5f7f09f027a355ddb022c79ed
|
|
| BLAKE2b-256 |
2373846f0662df2b4d551dd0bf00580b5040eb1e0ae87cd973205eed8fe20f27
|
Provenance
The following attestation bundles were made for makememe-0.1.9.tar.gz:
Publisher:
publish.yml on dhruvmehra/makememe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
makememe-0.1.9.tar.gz -
Subject digest:
75eff6fb848ee7641d786f7e76437c7b753f7063d8bf8e153b79a437e1553931 - Sigstore transparency entry: 1755142315
- Sigstore integration time:
-
Permalink:
dhruvmehra/makememe@c8149a6ae5dfd7829a5b80dcbadf39ef22dc4b41 -
Branch / Tag:
refs/tags/v0.1.9 - Owner: https://github.com/dhruvmehra
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c8149a6ae5dfd7829a5b80dcbadf39ef22dc4b41 -
Trigger Event:
release
-
Statement type:
File details
Details for the file makememe-0.1.9-py3-none-any.whl.
File metadata
- Download URL: makememe-0.1.9-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fed36deca46ca8438f7bb1bb1eb7d2abb71b8ca6f3b91f20517452664d809d3c
|
|
| MD5 |
c357ad5ecb752d163a21bb54c8a02512
|
|
| BLAKE2b-256 |
2bb53331cdaed7189b54f8cf6853cbf51277025fa9f7e4a57fe51212fa4c91e7
|
Provenance
The following attestation bundles were made for makememe-0.1.9-py3-none-any.whl:
Publisher:
publish.yml on dhruvmehra/makememe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
makememe-0.1.9-py3-none-any.whl -
Subject digest:
fed36deca46ca8438f7bb1bb1eb7d2abb71b8ca6f3b91f20517452664d809d3c - Sigstore transparency entry: 1755142331
- Sigstore integration time:
-
Permalink:
dhruvmehra/makememe@c8149a6ae5dfd7829a5b80dcbadf39ef22dc4b41 -
Branch / Tag:
refs/tags/v0.1.9 - Owner: https://github.com/dhruvmehra
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c8149a6ae5dfd7829a5b80dcbadf39ef22dc4b41 -
Trigger Event:
release
-
Statement type: