Claude Code can't generate images out of the box. But with a simple custom skill, you can add DALL-E image generation directly to your terminal workflow.

Here's how to set it up.

What We're Building

A skill that lets you say "generate an image of a sunset over mountains" and get a DALL-E generated image saved to your current directory. No browser, no copy-pasting API keys every time—just natural language to image.

Step 1: Create the Skill Directory

Skills live in ~/.claude/skills/. Create a folder for the image generator:

1mkdir -p ~/.claude/skills/image-generator

Step 2: Add Your API Key

Create a shared environment file for API keys:

1echo "OPENAI_API_KEY=sk-your-key-here" > ~/.claude/skills/.env

This file can be reused by other skills later.

Step 3: Create the Generation Script

Create ~/.claude/skills/image-generator/generate.js:

1#!/usr/bin/env node
2
3import { config } from "dotenv";
4import OpenAI from "openai";
5import fs from "fs";
6import path from "path";
7import { fileURLToPath } from "url";
8
9// Load .env from the skills folder
10const __dirname = path.dirname(fileURLToPath(import.meta.url));
11config({ path: path.join(__dirname, "..", ".env") });
12
13const apiKey = process.env.OPENAI_API_KEY;
14
15if (!apiKey || apiKey === "your-api-key-here") {
16  console.error("Error: Please set your OPENAI_API_KEY in ~/.claude/skills/.env");
17  process.exit(1);
18}
19
20// Parse arguments
21const args = process.argv.slice(2);
22const validSizes = ["1024x1024", "1792x1024", "1024x1792"];
23let size = "1024x1024";
24let promptParts = [];
25
26for (let i = 0; i < args.length; i++) {
27  if (args[i] === "--size" && args[i + 1]) {
28    size = args[i + 1];
29    i++; // Skip the size value
30  } else {
31    promptParts.push(args[i]);
32  }
33}
34
35const prompt = promptParts.join(" ");
36
37if (!prompt) {
38  console.error("Error: Please provide an image description");
39  console.error("Usage: node generate.js [--size <size>] <image description>");
40  console.error(`Valid sizes: ${validSizes.join(", ")}`);
41  process.exit(1);
42}
43
44if (!validSizes.includes(size)) {
45  console.error(`Error: Invalid size "${size}"`);
46  console.error(`Valid sizes: ${validSizes.join(", ")}`);
47  process.exit(1);
48}
49
50const openai = new OpenAI({ apiKey });
51
52async function generateImage() {
53  try {
54    console.log(`Generating image for: "${prompt}" (size: ${size})`);
55
56    const response = await openai.images.generate({
57      model: "dall-e-3",
58      prompt: prompt,
59      n: 1,
60      size: size,
61      quality: "standard",
62    });
63
64    const imageUrl = response.data[0].url;
65    const revisedPrompt = response.data[0].revised_prompt;
66
67    // Download the image
68    const imageResponse = await fetch(imageUrl);
69    const arrayBuffer = await imageResponse.arrayBuffer();
70    const buffer = Buffer.from(arrayBuffer);
71
72    // Save to current working directory with timestamp
73    const timestamp = Date.now();
74    const filename = `generated-image-${timestamp}.png`;
75    const outputPath = path.join(process.cwd(), filename);
76
77    fs.writeFileSync(outputPath, buffer);
78
79    console.log(`Image saved to: ${outputPath}`);
80    if (revisedPrompt) {
81      console.log(`Revised prompt: ${revisedPrompt}`);
82    }
83
84    return outputPath;
85  } catch (error) {
86    if (error.code === "invalid_api_key") {
87      console.error("Error: Invalid OpenAI API key");
88    } else if (error.code === "insufficient_quota") {
89      console.error("Error: OpenAI API quota exceeded");
90    } else {
91      console.error("Error generating image:", error.message);
92    }
93    process.exit(1);
94  }
95}
96
97generateImage();

Install the dependency:

1cd ~/.claude/skills/image-generator && npm init -y && npm install dotenv openai

Step 4: Create the Skill File

Create ~/.claude/skills/image-generator/skill.md:

1---
2name: image-generator
3description: Generate images using DALL-E 3
4tools:
5  - Bash
6  - Read
7---
8
9# Image Generator
10
11Generate images from text descriptions using DALL-E 3.
12
13## Usage
14
15Run the generation script with a description:
16
17node ~/.claude/skills/image-generator/generate.js [--size <size>] "your image description here"
18
19
20### Available Sizes
21
22- `1024x1024` - Square (default)
23- `1792x1024` - Landscape
24- `1024x1792` - Portrait
25
26## Examples
27
28node ~/.claude/skills/image-generator/generate.js "a serene mountain lake at sunset"
29node ~/.claude/skills/image-generator/generate.js --size 1792x1024 "panoramic city skyline"
30
31
32## Notes
33
34- Images save to the current working directory
35- DALL-E may revise your prompt for better results (shown in output)
36- Cost: ~$0.04 per image

Using It

Now in Claude Code, you can just ask:

"Generate an image of a robot writing code in a coffee shop"

Claude will recognize the intent, invoke the skill, and run the generation script. The image appears in your current directory.

You can also be explicit:

"/image-generator a minimalist logo for a tech startup"

Or specify dimensions:

"Generate a landscape image of northern lights over a forest"

Why This Works

Claude Code skills are markdown files that tell Claude:

  1. When to use the skill (the description field)
  2. How to use it (the instructions in the body)
  3. What tools it can access (Bash to run the script)

When you mention image generation, Claude matches your request to the skill's description and follows the instructions. It's that simple.

Tips for Better Results

Be specific with prompts. Instead of "a dog", say "a golden retriever puppy playing in autumn leaves, warm afternoon lighting".

Specify style when needed. Add "minimalist illustration", "photorealistic", "oil painting style", or "vector art" to guide the output.

Use landscape for blog covers. The 1792x1024 size works well for headers and social media cards.

You can even add a section to the skill.md file with example prompts for different styles of images (like prompts for oil painting style, or prompt for crayon drawing style etc)

Conclusion

This took about 10 minutes to set up. Now image generation is one natural language request away, integrated directly into your terminal workflow.

The pattern works for any API you want to expose to Claude—weather data, stock prices, database queries. Write a script, describe when to use it, and Claude handles the rest.