From fdf2edaa6a901f18e2b4ea60fdc4d63e6de3ac7d Mon Sep 17 00:00:00 2001 From: Zhongwei Li Date: Sun, 30 Nov 2025 09:03:17 +0800 Subject: [PATCH] Initial commit --- .claude-plugin/plugin.json | 12 +++ README.md | 3 + plugin.lock.json | 68 +++++++++++++++ skills/ai-image/.gitignore | 10 +++ skills/ai-image/README.md | 110 ++++++++++++++++++++++++ skills/ai-image/SKILL.md | 104 +++++++++++++++++++++++ skills/ai-image/main.py | 148 +++++++++++++++++++++++++++++++++ skills/ai-image/pyproject.toml | 10 +++ 8 files changed, 465 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 README.md create mode 100644 plugin.lock.json create mode 100644 skills/ai-image/.gitignore create mode 100644 skills/ai-image/README.md create mode 100644 skills/ai-image/SKILL.md create mode 100644 skills/ai-image/main.py create mode 100644 skills/ai-image/pyproject.toml diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..40e06e3 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "tchen-skills", + "description": "Tian Chen-specific skills", + "version": "0.0.0-2025.11.28", + "author": { + "name": "Tian Chen", + "email": "tyr.chen@gmail.com" + }, + "skills": [ + "./skills/ai-image" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..84c8236 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# tchen-skills + +Tian Chen-specific skills diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..5a3d916 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,68 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:tyrchen/claude-skills:tchen-skills", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "e78e6c8bd734d559999fb39416f2bbc5e416d97a", + "treeHash": "fcf7354f317292edf8b89d67cc41ee5eec931f5cb7ff8e2ff524b5c9321f2d65", + "generatedAt": "2025-11-28T10:28:47.900717Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "tchen-skills", + "description": "Tian Chen-specific skills" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "b2d22fd16b252314229f44d2e7c5a89adb50c9a986a17f5cbfb75ba211cf7418" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "095dd21b7e1ca5db7687082c6b883c12340bfab45a0d1991044d332c94bd5549" + }, + { + "path": "skills/ai-image/uv.lock", + "sha256": "ae25e7ca96d2f7a26b8feaa9116cf3646c738449fc065c7b432857cd033b0f54" + }, + { + "path": "skills/ai-image/pyproject.toml", + "sha256": "95d99c86f56782c2b3b7582c8e536bd07653ee020e554cd962746d935cbae7b6" + }, + { + "path": "skills/ai-image/README.md", + "sha256": "1a8f3f5c4ac21ce1759e22087f8878e3d29e25d96e39b878c71b885e94c6e05b" + }, + { + "path": "skills/ai-image/.gitignore", + "sha256": "ed7b84e816359d17276a801802de5c362c2c572ce3e50a8670c8362b08351380" + }, + { + "path": "skills/ai-image/SKILL.md", + "sha256": "00a6185b8f7f24df1140f620df49b49a9597de8815766fb0a2ccd7a026535578" + }, + { + "path": "skills/ai-image/.python-version", + "sha256": "7b55f8e67b5623c4bef3fa691288da9437d79d3aba156de48d481db32ac7d16d" + }, + { + "path": "skills/ai-image/main.py", + "sha256": "5b66ac92c85c757cb6a331bdc4360d3d724187b63eaaed808d83768536253fe4" + } + ], + "dirSha256": "fcf7354f317292edf8b89d67cc41ee5eec931f5cb7ff8e2ff524b5c9321f2d65" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/skills/ai-image/.gitignore b/skills/ai-image/.gitignore new file mode 100644 index 0000000..505a3b1 --- /dev/null +++ b/skills/ai-image/.gitignore @@ -0,0 +1,10 @@ +# Python-generated files +__pycache__/ +*.py[oc] +build/ +dist/ +wheels/ +*.egg-info + +# Virtual environments +.venv diff --git a/skills/ai-image/README.md b/skills/ai-image/README.md new file mode 100644 index 0000000..c057b9c --- /dev/null +++ b/skills/ai-image/README.md @@ -0,0 +1,110 @@ +# AI Image Generation Skill + +A Claude Code skill for generating high-quality AI images using OpenAI's **gpt-image-1** model with customizable aspect ratios and artistic themes. + +## Features + +- Generate images from text prompts using OpenAI's latest gpt-image-1 model +- Choose from multiple aspect ratios (vertical, horizontal, square) +- Apply different artistic themes (Studio Ghibli, futuristic, Pixar, oil painting, Chinese painting) +- Customizable output location +- High-quality image generation up to 4096x4096 pixels +- Base64 image handling for reliable downloads + +## Installation + +This is a Claude Code skill. To use it: + +1. Ensure you have [uv](https://github.com/astral-sh/uv) installed +2. Clone or place this skill in your project +3. Set your OpenAI API key: + +```bash +export OPENAI_API_KEY='your-api-key-here' +``` + +Note: Using gpt-image-1 requires organization verification on [platform.openai.com](https://platform.openai.com). + +## Usage + +### Basic Usage + +```bash +uv run main.py --prompt "a cat sitting on a tree" +``` + +### With Style and Theme + +```bash +uv run main.py --prompt "a sunset over mountains" --style horizontal --theme oil-paint --output ./sunset.png +``` + +### More Examples + +```bash +# Futuristic portrait +uv run main.py --prompt "a robot in a city" --style vertical --theme futuristic --output ./robot.png + +# Studio Ghibli landscape +uv run main.py --prompt "a magical forest with spirits" --style horizontal --theme ghibli --output ./forest.png + +# Pixar-style character +uv run main.py --prompt "a friendly dragon" --style square --theme pixar --output ./dragon.png +``` + +## Options + +- `--prompt`: Text description of the image to generate (required) +- `--style`: Image aspect ratio (default: square) + - `vertical`: 1024x1536 pixels (portrait) + - `horizontal`: 1536x1024 pixels (landscape) + - `square`: 1024x1024 pixels +- `--theme`: Artistic theme (optional) + - `ghibli`: Studio Ghibli animation style + - `futuristic`: Sci-fi with sleek designs and neon lights + - `pixar`: Vibrant 3D animation style + - `oil-paint`: Classical oil painting with textures + - `chinese-paint`: Traditional Chinese ink painting +- `--output`: Output file path (default: ./generated_image.png) + +## Technical Details + +- **Model**: OpenAI gpt-image-1 (released April 2025) +- **Supported Sizes**: 1024x1024, 1024x1536, 1536x1024 +- **Maximum Resolution**: Up to 4096x4096 pixels +- **Response Format**: Base64 encoded images (b64_json) +- **Dependencies**: openai>=2.7.1 + +## Pricing + +Usage is priced per token: +- Text tokens: $5 per million +- Image input tokens: $10 per million +- Image output tokens: $40 per million + +Approximate costs per generated image: +- Low quality square: ~$0.02 +- Medium quality square: ~$0.07 +- High quality square: ~$0.19 + +## Troubleshooting + +### API Key Not Set + +If you see "Error: OPENAI_API_KEY environment variable not set": + +```bash +export OPENAI_API_KEY='your-api-key-here' +``` + +### Organization Not Verified + +gpt-image-1 requires organization verification. Visit [platform.openai.com](https://platform.openai.com) and complete the verification process in your account settings. + +### Invalid Size Error + +Ensure you're using one of the supported aspect ratios: `vertical`, `horizontal`, or `square`. + +## License + +This skill is provided as-is for use with Claude Code. diff --git a/skills/ai-image/SKILL.md b/skills/ai-image/SKILL.md new file mode 100644 index 0000000..8cb0071 --- /dev/null +++ b/skills/ai-image/SKILL.md @@ -0,0 +1,104 @@ +--- +name: ai-image +description: Generate AI images using OpenAI's gpt-image-1 model with customizable aspect ratios and artistic themes. Use when the user wants to create images, generate artwork, or mentions image generation with specific styles like Ghibli, futuristic, Pixar, oil painting, or Chinese painting. +--- + +# AI Image Generation Skill + +Generate high-quality AI images using OpenAI's gpt-image-1 model with customizable styles and themes. + +## When to Use This Skill + +Use this skill when the user wants to: +- Generate images from text descriptions +- Create artwork with specific artistic styles +- Generate images with particular aspect ratios (vertical, horizontal, square) +- Apply themed visual styles (Studio Ghibli, futuristic, Pixar, oil painting, Chinese painting) + +## Instructions + +1. **Check for API Key**: Verify that the OPENAI_API_KEY environment variable is set +2. **Gather Requirements**: Ask the user for: + - Image prompt (required) + - Style/aspect ratio: vertical (1024x1536), horizontal (1536x1024), or square (1024x1024) + - Theme: ghibli, futuristic, pixar, oil-paint, or chinese-paint (optional) + - Output location (optional, defaults to ./generated_image.png) +3. **Run the CLI**: Execute the main.py script with the appropriate parameters +4. **Report Results**: Show the user where the image was saved and any relevant details + +## Available Options + +### Aspect Ratios (--style) +- `vertical`: 1024x1536 pixels (portrait orientation) +- `horizontal`: 1536x1024 pixels (landscape orientation) +- `square`: 1024x1024 pixels (default) + +### Artistic Themes (--theme) +- `ghibli`: Studio Ghibli animation style with whimsical, dreamlike aesthetics +- `futuristic`: Sci-fi style with sleek designs and neon lights +- `pixar`: Vibrant 3D animation style with expressive characters +- `oil-paint`: Classical oil painting with rich textures and brushstrokes +- `chinese-paint`: Traditional Chinese ink painting with delicate brushwork + +## Usage Examples + +### Basic Usage +```bash +uv run main.py --prompt "a cat sitting on a tree" +``` + +### With Style and Theme +```bash +uv run main.py --prompt "a sunset over mountains" --style horizontal --theme oil-paint --output ./sunset.png +``` + +### Futuristic Portrait +```bash +uv run main.py --prompt "a robot in a city" --style vertical --theme futuristic --output ./robot.png +``` + +### Studio Ghibli Landscape +```bash +uv run main.py --prompt "a magical forest with spirits" --style horizontal --theme ghibli --output ./forest.png +``` + +## Setup Requirements + +This skill requires an OpenAI API key with access to the gpt-image-1 model: + +```bash +export OPENAI_API_KEY='your-api-key-here' +``` + +Note: Using gpt-image-1 requires organization verification on the OpenAI platform. + +## Technical Details + +- **Model**: OpenAI gpt-image-1 (released April 2025) +- **Response Format**: Base64 encoded images (b64_json) +- **Supported Sizes**: 1024x1024, 1024x1536, 1536x1024 +- **Maximum Resolution**: Up to 4096x4096 pixels +- **Dependencies**: openai>=2.7.1 + +## Pricing Information + +Usage is priced per token: +- Text tokens: $5 per million +- Image input tokens: $10 per million +- Image output tokens: $40 per million + +Approximate costs per generated image: +- Low quality square: ~$0.02 +- Medium quality square: ~$0.07 +- High quality square: ~$0.19 + +## Troubleshooting + +### API Key Not Set +If you see "Error: OPENAI_API_KEY environment variable not set", ensure your API key is exported in your shell session. + +### Organization Not Verified +gpt-image-1 requires organization verification on platform.openai.com. Visit your OpenAI account settings to complete verification. + +### Invalid Size Error +Ensure you're using one of the supported sizes: 1024x1024, 1024x1536, or 1536x1024. diff --git a/skills/ai-image/main.py b/skills/ai-image/main.py new file mode 100644 index 0000000..954324f --- /dev/null +++ b/skills/ai-image/main.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +""" +AI Image Generation Skill +Generate images using OpenAI's gpt-image-1 model with customizable styles and themes. +""" + +import os +import sys +import base64 +from pathlib import Path +import click +from openai import OpenAI + + +# Image style configurations (aspect ratio) +# gpt-image-1 supports: 1024x1024, 1024x1536, 1536x1024, or "auto" +STYLES = { + "vertical": "1024x1536", + "horizontal": "1536x1024", + "square": "1024x1024" +} + +# Theme descriptions for prompt engineering +THEMES = { + "ghibli": "in the style of Studio Ghibli animation, whimsical and dreamlike with soft colors and hand-drawn aesthetic", + "futuristic": "in a futuristic sci-fi style with sleek designs, neon lights, and advanced technology", + "pixar": "in Pixar animation style with vibrant colors, expressive characters, and polished 3D rendering", + "oil-paint": "as an oil painting with rich textures, visible brushstrokes, and classical artistic composition", + "chinese-paint": "in traditional Chinese ink painting style with delicate brushwork, minimalist composition, and ethereal atmosphere" +} + + +def enhance_prompt(prompt: str, theme: str = None) -> str: + """Enhance the user prompt with theme description if specified.""" + if theme and theme in THEMES: + return f"{prompt}, {THEMES[theme]}" + return prompt + + +def generate_image(prompt: str, style: str, theme: str, output: str): + """Generate an image using OpenAI's gpt-image-1 model.""" + + # Check for API key + api_key = os.getenv("OPENAI_API_KEY") + if not api_key: + click.echo(click.style("Error: OPENAI_API_KEY environment variable not set", fg="red"), err=True) + click.echo("Please set your OpenAI API key: export OPENAI_API_KEY='your-key-here'", err=True) + sys.exit(1) + + # Initialize OpenAI client + client = OpenAI(api_key=api_key) + + # Enhance prompt with theme + enhanced_prompt = enhance_prompt(prompt, theme) + size = STYLES[style] + + click.echo(click.style("Generating image...", fg="cyan")) + click.echo(f"Prompt: {enhanced_prompt}") + click.echo(f"Size: {size}") + + try: + # Generate image using gpt-image-1 + # Note: gpt-image-1 returns b64_json format, not URLs + response = client.images.generate( + model="gpt-image-1", + prompt=enhanced_prompt, + size=size, + n=1, + ) + + # Get the base64 encoded image + # gpt-image-1 returns images as base64 encoded data + if hasattr(response.data[0], 'b64_json') and response.data[0].b64_json: + image_data = base64.b64decode(response.data[0].b64_json) + elif hasattr(response.data[0], 'url') and response.data[0].url: + # Fallback to URL if b64_json is not available + import httpx + image_data = httpx.get(response.data[0].url).content + else: + raise Exception("No image data received from API") + + # Ensure output directory exists + output_path = Path(output) + output_path.parent.mkdir(parents=True, exist_ok=True) + + # Save the image + with open(output_path, "wb") as f: + f.write(image_data) + + click.echo() + click.echo(click.style("✓ Image generated successfully!", fg="green", bold=True)) + click.echo(f"Saved to: {click.style(str(output_path.absolute()), fg='blue')}") + + # Print the revised prompt if the model modified it + if hasattr(response.data[0], 'revised_prompt') and response.data[0].revised_prompt: + click.echo() + click.echo(click.style("Revised prompt:", fg="yellow")) + click.echo(response.data[0].revised_prompt) + + except Exception as e: + click.echo(click.style(f"Error generating image: {str(e)}", fg="red"), err=True) + sys.exit(1) + + +@click.command() +@click.option( + "--prompt", "-p", + required=True, + help="Text description of the image to generate" +) +@click.option( + "--style", "-s", + type=click.Choice(list(STYLES.keys()), case_sensitive=False), + default="square", + show_default=True, + help="Image aspect ratio" +) +@click.option( + "--theme", "-t", + type=click.Choice(list(THEMES.keys()), case_sensitive=False), + help="Artistic theme to apply" +) +@click.option( + "--output", "-o", + default="./generated_image.png", + type=click.Path(), + show_default=True, + help="Output file path" +) +def main(prompt, style, theme, output): + """ + Generate AI images using OpenAI's gpt-image-1 model. + + \b + Examples: + python main.py -p "a cat sitting on a tree" + python main.py -p "a sunset over mountains" -s horizontal -t oil-paint + python main.py -p "a robot in a city" -s vertical -t futuristic -o robot.png + + \b + Available styles: vertical, horizontal, square + Available themes: ghibli, futuristic, pixar, oil-paint, chinese-paint + """ + generate_image(prompt=prompt, style=style, theme=theme, output=output) + + +if __name__ == "__main__": + main() diff --git a/skills/ai-image/pyproject.toml b/skills/ai-image/pyproject.toml new file mode 100644 index 0000000..0734f87 --- /dev/null +++ b/skills/ai-image/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "ai-image" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "click>=8.3.0", + "openai>=2.7.1", +]