v3.18.0: docs sync -- internal agents hidden from public docs, brewui shipped empty-but-installable, skill/agent counts recomputed (32 skills, 16 agents)

This commit is contained in:
kochetkov-ma
2026-06-27 12:04:45 +01:00
parent 18f0357ef6
commit c2283ad347
56 changed files with 158 additions and 3077 deletions
+14 -12
View File
@@ -6,13 +6,13 @@
},
"metadata": {
"description": "Claude Code plugin suite: brewcode for infinite task execution, brewdoc for documentation tools, brewtools for text utilities, brewui for UI/visual/creative tools",
"version": "3.17.0"
"version": "3.18.0"
},
"plugins": [
{
"name": "brewcode",
"description": "Brewcode - full-featured development platform for Claude Code: infinite focus tasks, prompt optimization, skill/agent creation, quorum reviews, rules management",
"version": "3.17.0",
"version": "3.18.0",
"category": "productivity",
"keywords": [
"brewcode",
@@ -46,7 +46,7 @@
{
"name": "brewdoc",
"description": "Brewdoc - Claude Code documentation tools: auto-sync for skills/agents/rules, my-claude installation docs, memory optimization, md-to-pdf conversion",
"version": "3.17.0",
"version": "3.18.0",
"category": "productivity",
"keywords": [
"brewdoc",
@@ -74,7 +74,7 @@
{
"name": "brewtools",
"description": "Brewtools - universal utilities for Claude Code: text optimization, humanization, secrets scanning",
"version": "3.17.0",
"version": "3.18.0",
"category": "productivity",
"keywords": [
"brewtools",
@@ -101,18 +101,20 @@
},
{
"name": "brewui",
"description": "Brewui - UI/visual/creative tools for Claude Code: AI image generation",
"version": "3.17.0",
"description": "Placeholder for future UI/visual/creative tools (currently empty, installable)",
"version": "3.18.0",
"category": "productivity",
"keywords": [
"brewui",
"image-generation",
"visual-tools"
"ui",
"visual",
"creative",
"placeholder"
],
"tags": [
"image-generation",
"visual-tools",
"creative"
"ui",
"visual",
"creative",
"placeholder"
],
"author": {
"name": "Maksim Kochetkov",
+10 -17
View File
@@ -10,7 +10,7 @@
**Claude Code plugin suite** -- four plugins for development, documentation, text utility, and visual workflows.
A regular Claude Code session loses context during compaction. Brewcode automatically saves knowledge, passes state between compaction cycles, and continues work without restarting. Four plugins. 33 skills. 16 agents. 9 lifecycle hooks.
A regular Claude Code session loses context during compaction. Brewcode automatically saves knowledge, passes state between compaction cycles, and continues work without restarting. Four plugins. 32 skills. 16 agents. 9 lifecycle hooks.
[**Full Documentation**](https://doc-claude.brewcode.app/getting-started/)
@@ -59,7 +59,7 @@ After all commands succeed, run `/reload-plugins`. If `/reload-plugins` is unava
| [brewcode](brewcode/README.md) | Infinite task execution, quorum reviews, skill/agent creation, semantic search | 13 | `claude plugin install brewcode@claude-brewcode` |
| [brewdoc](brewdoc/README.md) | Documentation tools: auto-sync, memory optimization, PDF conversion, publishing | 6 | `claude plugin install brewdoc@claude-brewcode` |
| [brewtools](brewtools/README.md) | Universal text utilities: token optimization, humanization, secrets scanning, plugin updates | 13 | `claude plugin install brewtools@claude-brewcode` |
| [brewui](brewui/README.md) | UI/visual tools: AI image generation via multiple providers | 1 | `claude plugin install brewui@claude-brewcode` |
| [brewui](brewui/README.md) | UI/visual/creative tools (placeholder, currently empty) | 0 | `claude plugin install brewui@claude-brewcode` |
## Installation
@@ -151,11 +151,7 @@ After `/brewcode:setup`, each task follows the cycle: `spec` -> `plan` -> `start
### brewui -- visual tools
```bash
/brewui:image-gen "a cozy coffee shop at sunset" # Generate image (default)
/brewui:image-gen --edit photo.png "add warm lighting" # Edit existing image
/brewui:image-gen --config # Configure API keys
```
Placeholder plugin, currently empty. No commands yet -- coming soon.
## How It Works
@@ -204,7 +200,6 @@ After `/brewcode:setup`, each task follows the cycle: `spec` -> `plan` -> `start
| `/brewcode:skills` | List, create, and upgrade skills |
| `/brewcode:agents` | Interactive agent creation and improvement |
| `/brewcode:e2e` | E2E testing orchestration with BDD scenarios |
| `/brewcode:debate` | Evidence-based multi-agent debate (Challenge, Strategy, Critic modes) |
| `/brewcode:teardown` | Remove plugin configuration (keeps task data) |
### Brewdoc (6 skills)
@@ -236,11 +231,9 @@ After `/brewcode:setup`, each task follows the cycle: `spec` -> `plan` -> `start
| `/brewtools:manager` | Manager mode -- codewords ++m/++mp inject a delegate-everything prompt; HARD wall (on/off/uninstall) installs a project PreToolUse guard that blocks main-session edits, forcing delegation |
| `/brewtools:task-board-init` | Deploy a file-based Kanban into ANY repo via multi-agent analysis -- task-tracker agent, task-board skill, tasks rule, .claude/features |
### Brewui (1 skill)
### Brewui (0 skills)
| Skill | Purpose |
|-------|---------|
| `/brewui:image-gen` | AI image generation via multiple providers with anti-slop controls |
No skills yet -- placeholder for future UI/visual/creative tools.
### Portable skills (standalone)
@@ -266,11 +259,11 @@ Self-contained `SKILL.md` folders that ship outside the four plugins -- drop the
| text-optimizer | sonnet | Optimize text and docs for LLM efficiency |
| ssh-admin | opus | Linux server administration via SSH |
| deploy-admin | opus | GitHub Actions deployment and CI/CD |
| bc-coordinator | haiku | Task coordination, artifact management |
| bc-knowledge-manager | haiku | KNOWLEDGE.jsonl compaction and deduplication |
| bc-grepai-configurator | opus | Generate grepai config.yaml |
| bd-auto-sync-processor | sonnet | Process documents for auto-sync |
| bc-rules-organizer | sonnet | Create and optimize `.claude/rules/` files |
| bc-coordinator | haiku | Internal: spawned by /brewcode:start + post-task hook |
| bc-knowledge-manager | haiku | Internal: spawned by /brewcode:start |
| bc-grepai-configurator | opus | Internal: spawned by /brewcode:grepai |
| bd-auto-sync-processor | sonnet | Internal: spawned by /brewdoc:auto-sync |
| bc-rules-organizer | sonnet | Internal: spawned by /brewcode:rules |
## Documentation
+30
View File
@@ -2,6 +2,36 @@
---
## v3.18.0 (2026-06-27)
> Docs: [brewui overview](https://doc-claude.brewcode.app/brewui/overview/) | [brewui skills](https://doc-claude.brewcode.app/brewui/skills/) | [brewcode agents](https://doc-claude.brewcode.app/brewcode/agents/) | [brewdoc auto-sync](https://doc-claude.brewcode.app/brewdoc/skills/auto-sync/)
Documentation sync to reality: internal agents hidden from public docs, brewui shipped as an empty-but-installable placeholder, and skill/agent counts recomputed across all doc levels. Skill total is now 32; shipped agents 16.
### brewui
#### Changed
- **plugin:** now ships as an empty, installable placeholder for future UI/visual/creative tools. The `image-gen` skill was removed and `skills/` is empty. Installing brewui still registers its hooks and reserves the `/brewui:*` namespace, with no commands yet.
- **docs:** overview, skills, and agents pages rewritten to a "coming soon" placeholder; README, plugin manifest, and marketplace entry updated to the placeholder description.
### brewcode
#### Changed
- **agents:** `bc-coordinator`, `bc-knowledge-manager`, `bc-grepai-configurator`, and `bc-rules-organizer` are now documented as internal (spawned only by skills and hooks). Their dedicated doc pages were removed; summary tables, navigation, the architecture overview, and the README mark them internal with no deep links.
- **docs:** removed a spurious `/brewcode:debate` row from the skill tables (debate is a brewtools skill); the brewcode skill count stays 13 and the suite total is recomputed to 32.
### brewdoc
#### Changed
- **agents:** `bd-auto-sync-processor` documented as internal across the README, overview, the auto-sync skill page, and the guide catalog.
### brewtools
#### Changed
- **skill-toggle:** running example updated from the removed `brewui:image-gen` to the existing `brewdoc:md-to-pdf`.
---
## v3.17.0 (2026-06-27)
> Docs: [brewcode hooks](https://doc-claude.brewcode.app/brewcode/hooks/) | [brewtools manager](https://doc-claude.brewcode.app/brewtools/skills/manager/)
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "brewcode",
"version": "3.17.0",
"version": "3.18.0",
"description": "Brewcode - full-featured development platform for Claude Code: infinite focus tasks, prompt optimization, skill/agent creation, quorum reviews, rules management",
"author": {
"name": "Maksim Kochetkov",
+5 -6
View File
@@ -4,7 +4,7 @@
| Field | Value |
|-------|-------|
| Version | 3.17.0 |
| Version | 3.18.0 |
| Skills | 13 |
| Agents | 12 |
| Hooks | 9 |
@@ -89,7 +89,6 @@ After `/brewcode:setup`, each task follows the cycle: `spec` -> `plan` -> `start
| [`/brewcode:skills`](skills/skills/README.md) | Skill management: list, create, upgrade with activation optimization |
| [`/brewcode:agents`](skills/agents/README.md) | Interactive agent creation and improvement |
| [`/brewcode:e2e`](skills/e2e/README.md) | E2E testing orchestration with BDD scenarios and quorum review |
| [`/brewcode:debate`](skills/debate/README.md) | Evidence-based multi-agent debate: Challenge, Strategy, Critic modes |
| [`/brewcode:teardown`](skills/teardown/README.md) | Plugin configuration cleanup (tasks are preserved) |
> **Note:** `/brewcode:review` is a local skill created in the project during `/brewcode:setup`.
@@ -106,10 +105,10 @@ After `/brewcode:setup`, each task follows the cycle: `spec` -> `plan` -> `start
| [agent-creator](agents/agent-creator.md) | opus | Create and improve Claude Code agents |
| [hook-creator](agents/hook-creator.md) | opus | Create and debug Claude Code hooks |
| [bash-expert](agents/bash-expert.md) | opus | Create professional shell scripts |
| [bc-coordinator](agents/bc-coordinator.md) | haiku | Task coordination, artifact management |
| [bc-knowledge-manager](agents/bc-knowledge-manager.md) | haiku | KNOWLEDGE.jsonl compaction and deduplication |
| [bc-grepai-configurator](agents/bc-grepai-configurator.md) | opus | Generate grepai config.yaml |
| [bc-rules-organizer](agents/bc-rules-organizer.md) | haiku | Create and optimize `.claude/rules/` files |
| bc-coordinator | haiku | Internal: spawned by /brewcode:start + post-task hook |
| bc-knowledge-manager | haiku | Internal: spawned by /brewcode:start |
| bc-grepai-configurator | opus | Internal: spawned by /brewcode:grepai |
| bc-rules-organizer | sonnet | Internal: spawned by /brewcode:rules |
> **Dynamic teams:** Use `/brewcode:teams create` to generate 5-20 project-specific agents with self-selection protocol and performance tracking.
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "claude-plugin-brewcode",
"version": "3.17.0",
"version": "3.18.0",
"description": "Infinite task execution with automatic handoff for Claude Code",
"keywords": [
"claude-code",
@@ -36,6 +36,6 @@
},
"claude-plugin": {
"name": "brewcode",
"version": "3.17.0"
"version": "3.18.0"
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "brewdoc",
"version": "3.17.0",
"version": "3.18.0",
"description": "Brewdoc - Claude Code documentation tools: auto-sync for skills/agents/rules, my-claude installation docs, memory optimization",
"author": {
"name": "Maksim Kochetkov",
+2 -2
View File
@@ -4,7 +4,7 @@
| Field | Value |
|-------|-------|
| Version | 3.4.29 |
| Version | 3.18.0 |
| Skills | 6 |
| Agents | 1 |
| Hooks | 1 |
@@ -91,7 +91,7 @@ claude --plugin-dir ./brewdoc
| Agent | Model | Purpose |
|-------|-------|---------|
| [bd-auto-sync-processor](agents/bd-auto-sync-processor.md) | sonnet | Process documents for auto-sync |
| bd-auto-sync-processor | sonnet | Internal: spawned by /brewdoc:auto-sync |
## Architecture
+1 -1
View File
@@ -29,7 +29,7 @@ Guide walks you through every feature of the plugin suite across three progressi
| A: Getting Started | installation | Marketplace setup, installing plugins, verifying versions |
| B: Core Workflow | killer-flow | The infinite task pipeline: spec, plan, start |
| B: Core Workflow | teams | Dynamic agent teams with self-selection and tracking |
| B: Core Workflow | skills-catalog | All 33 skills with trigger examples |
| B: Core Workflow | skills-catalog | All 32 skills with trigger examples |
| C: Mastery | agents-catalog | All 16 agents with roles and model selection |
| C: Mastery | customization | Create custom skills, agents, and hooks |
| C: Mastery | integration | CLAUDE.md, rules, memory, teams directory |
@@ -36,11 +36,11 @@ These agents ship with the brewcode plugin suite. Available immediately after in
| agent-creator | brewcode | opus | Create/update Claude Code agents |
| hook-creator | brewcode | opus | Create/debug Claude Code hooks |
| bash-expert | brewcode | opus | Create professional sh/bash scripts |
| bc-coordinator | brewcode | haiku | Task coordination, artifact management, 2-step protocol |
| bc-knowledge-manager | brewcode | haiku | KNOWLEDGE.jsonl compaction and dedup |
| bc-grepai-configurator | brewcode | opus | grepai config.yaml generation |
| bc-rules-organizer | brewcode | sonnet | .claude/rules/*.md organization |
| bd-auto-sync-processor | brewdoc | sonnet | Single document sync processing |
| bc-coordinator | brewcode | haiku | Internal. Spawned only by /brewcode:start + post-task hook. No direct/auto use. |
| bc-knowledge-manager | brewcode | haiku | Internal. Spawned only by /brewcode:start. No direct/auto use. |
| bc-grepai-configurator | brewcode | opus | Internal. Spawned only by /brewcode:grepai. No direct/auto use. |
| bc-rules-organizer | brewcode | sonnet | Internal. Spawned only by /brewcode:rules. No direct/auto use. |
| bd-auto-sync-processor | brewdoc | sonnet | Internal. Spawned only by /brewdoc:auto-sync. No direct/auto use. |
| text-optimizer | brewtools | sonnet | Text/docs token optimization |
| ssh-admin | brewtools | opus | SSH server management |
| deploy-admin | brewtools | opus | GitHub Actions deployment |
@@ -22,7 +22,7 @@ One marketplace, four plugins, one version number. Install what you need.
| brewcode | Infinite task execution, agent teams, project automation | setup, spec, plan, start, teams, review, convention, e2e |
| brewdoc | Documentation tools: sync, generate, optimize, publish | auto-sync, my-claude, memory, md-to-pdf, guide, publish |
| brewtools | Universal utilities: text optimization, security scanning | text-optimize, text-human, secrets-scan, ssh, deploy, debate, plugin-update |
| brewui | UI/visual/creative tools | image-gen |
| brewui | UI/visual/creative tools (placeholder, empty) | (none yet) |
**brewcode** is the core. It runs tasks that survive context limits through automatic handoff. It manages agents, hooks, and knowledge persistence.
@@ -30,7 +30,7 @@ One marketplace, four plugins, one version number. Install what you need.
**brewtools** provides standalone utilities. Text-optimize reduces token usage in prompts. Secrets-scan catches leaked credentials. SSH and deploy handle server management and CI/CD workflows. These work in any project.
**brewui** handles UI and visual tasks. Image-gen creates AI images via multiple providers.
**brewui** is a placeholder for future UI/visual/creative tools; it is currently empty.
## Section 3: How They Work Together
@@ -39,7 +39,7 @@ The plugins complement each other:
- **brewcode** handles the heavy lifting: task execution, planning, code review, convention extraction
- **brewdoc** keeps documentation in sync with your codebase as it evolves
- **brewtools** provides utility skills you can call from anywhere
- **brewui** generates images and converts designs to code
- **brewui** is a placeholder for future UI/visual/creative tools (currently empty)
All four share the same version number. They update together from the same marketplace. No version mismatches.
@@ -61,13 +61,9 @@ Universal utilities. Work in any project, no setup needed.
These are standalone — no project configuration required. Run them anywhere.
## Section 3b: Brewui Skills (1)
## Section 3b: Brewui Skills (0)
UI/visual/creative tools. AI image generation via multiple providers.
| Skill | Purpose |
|-------|---------|
| `/brewui:image-gen` | AI image generation via multiple providers with anti-slop controls |
Brewui currently ships no skills -- placeholder for future UI/visual/creative tools.
## Section 4: Common Patterns
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "brewtools",
"version": "3.17.0",
"version": "3.18.0",
"description": "Brewtools - universal utilities for Claude Code: text optimization, humanization, secrets scanning",
"author": {
"name": "Maksim Kochetkov",
+1 -1
View File
@@ -4,7 +4,7 @@
| Field | Value |
|-------|-------|
| Version | 3.12.0 |
| Version | 3.18.0 |
| Skills | 13 |
| Agents | 3 |
+4 -4
View File
@@ -49,7 +49,7 @@ Default for "disable" intent without explicit mode: `off`.
- User prompt is freeform without concrete `plugin:name` (e.g. "отключи лишнее"), OR
- Parsed target missing from cache.
**Skip interactive (go straight to P0 → P2 → P4)** when op AND target both explicit: `/brewtools:skill-toggle disable brewui:image-gen`.
**Skip interactive (go straight to P0 → P2 → P4)** when op AND target both explicit: `/brewtools:skill-toggle disable brewdoc:md-to-pdf`.
| Phase | Action | Tool |
|-------|--------|------|
@@ -65,7 +65,7 @@ Terminal ops (`list`, `status`) skip to I4 directly.
```
DISABLED RIGHT NOW (via skillOverrides)
---------------------------------------
brewui:image-gen off
brewdoc:md-to-pdf off
brewdoc:md-to-pdf user-invocable-only
(none) <-- if empty
ENABLED (M skills across P plugins)
@@ -83,7 +83,7 @@ Parse `$ARGUMENTS` (or NL prompt) into:
Rules:
- Default mode for `disable` = `off`. User can specify e.g. `--mode=user-invocable-only` or "make it slash-only".
- Target format: `plugin:name` (e.g., `brewui:image-gen`). Bare `name` → AskUserQuestion which plugin.
- Target format: `plugin:name` (e.g., `brewdoc:md-to-pdf`). Bare `name` → AskUserQuestion which plugin.
- `status`, `list` take no targets.
- Multiple targets allowed for disable/enable — iterate P2 per target.
- No `--scope` flag — `skillOverrides` is global-only (per Claude Code design).
@@ -156,7 +156,7 @@ Confirm `PLUGIN:NAME` present (for disable) or absent (for enable). Render resul
| Plugin | Name | Mode | Action | File |
|--------|------|------|--------|------|
| brewui | image-gen | off | written | ~/.claude/settings.json |
| brewdoc | md-to-pdf | off | written | ~/.claude/settings.json |
> Restart session or `/reload-plugins` for the change to take effect.
> Persisted to ~/.claude/settings.json — survives plugin updates.
+6 -4
View File
@@ -1,7 +1,7 @@
{
"name": "brewui",
"version": "3.17.0",
"description": "Brewui - UI/visual/creative tools for Claude Code: AI image generation",
"version": "3.18.0",
"description": "Brewui -- placeholder for future UI/visual/creative tools",
"author": {
"name": "Maksim Kochetkov",
"email": "apmatypa88@gmail.com",
@@ -12,8 +12,10 @@
"license": "MIT",
"keywords": [
"brewui",
"image-generation",
"visual-tools"
"ui",
"visual",
"creative",
"placeholder"
],
"skills": "./skills/"
}
+7 -24
View File
@@ -1,11 +1,11 @@
# Brewui
> UI/visual/creative tools plugin for Claude Code -- AI image generation via multiple providers.
> UI/visual/creative tools plugin for Claude Code -- placeholder, currently empty but installable.
| Field | Value |
|-------|-------|
| Version | 3.4.42 |
| Skills | 1 |
| Version | 3.18.0 |
| Skills | 0 |
## Install
@@ -40,7 +40,7 @@ Update anytime with `/brewtools:plugin-update`.
## Overview
Brewui provides visual and creative tools for Claude Code: AI image generation via multiple providers (Gemini Imagen 4, OpenRouter, OpenAI DALL-E 3) with anti-AI-slop controls. Each skill is self-contained.
Brewui is a placeholder plugin for future UI/visual/creative tools. It currently ships no skills or agents, but installs cleanly and registers its hooks so it can be wired into your suite ahead of time. Content will be added in a future release.
## Installation
@@ -57,21 +57,9 @@ claude plugin update brewui@claude-brewcode
claude --plugin-dir ./brewui
```
## Quick Start
```bash
/brewui:image-gen "a cozy coffee shop at sunset" # Generate (default)
/brewui:image-gen --edit photo.png "add warm lighting" # Edit existing
/brewui:image-gen --config # Configure API keys
/brewui:image-gen --style illustration "tech blog header" # Illustration style
/brewui:image-gen --service openrouter "mountain lake" # Specific provider
```
## Skills
| Skill | Purpose | Model | Arguments |
|-------|---------|-------|-----------|
| [`/brewui:image-gen`](skills/image-gen/SKILL.md) | AI image generation via 4 providers | haiku | `[prompt] [--edit] [--config] [--update] [--service] [--style] [--count] [--output] [--size]` |
No skills yet -- coming soon. Brewui is an empty placeholder; the `/brewui:*` command namespace is reserved for future tools.
## Architecture
@@ -82,13 +70,9 @@ brewui/
├── hooks/
│ ├── hooks.json # Hook registry
│ ├── session-start.mjs # BU_PLUGIN_ROOT injection
│ ├── pre-task.mjs # BU_PLUGIN_ROOT into subagents
│ └── lib/utils.mjs # I/O utilities
├── skills/
│ └── image-gen/ # AI image generation
│ ├── SKILL.md
│ ├── references/ # Provider specs, anti-slop, modes
│ ├── scripts/ # API request, parsing, saving
│ └── tests/ # Integration tests
├── skills/ # Empty -- placeholder for future tools
└── README.md
```
@@ -98,7 +82,6 @@ Full docs: [doc-claude.brewcode.app/brewui/overview](https://doc-claude.brewcode
| Resource | Link |
|----------|------|
| Image Gen | [image-gen](https://doc-claude.brewcode.app/brewui/skills/image-gen/) |
| Release Notes | [RELEASE-NOTES.md](../RELEASE-NOTES.md) |
Author: Maksim Kochetkov | License: MIT
View File
-275
View File
@@ -1,275 +0,0 @@
---
name: brewui:image-gen
description: "Generate AI images via OpenRouter, Imagen 4, DALL-E 3, anti-slop. Triggers: generate image, AI image, og image."
user-invocable: true
argument-hint: "[prompt] [--edit image.png 'instructions'] [--config] [--update] [--service gemini|openrouter|openai] [--style photo|illustration|art] [--count N] [--output dir] [--size WxH]"
allowed-tools: [Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, WebSearch]
model: haiku
---
<instructions>
# Image Gen
Generates AI images via Gemini Imagen 4, OpenRouter (Gemini 2.5 Flash Image / GPT-5-image), or OpenAI DALL-E 3. Applies anti-AI-slop prompt prefixes per style. Four modes: generate, edit, config, update.
**Arguments:** `$ARGUMENTS`
## Mode Routing
| Mode | Flow |
|------|------|
| generate | Phase 0 -> 1 -> 2 -> 3 -> 4 |
| edit | Phase 0 -> 1 -> 2E -> 3 -> 4 |
| config | Phase 0 -> C |
| update | Phase 0 -> U |
> **MODE DETECTION:** Priority order:
> 1. Explicit flags: `--edit`, `--config`, `--update` override everything
> 2. Context signals: edit ("edit this", "modify image", "change the" + image path) -> **edit**; config ("setup", "configure", "set key") -> **config**; update ("check providers", "update models") -> **update**
> 3. Default: **generate**
>
> **FAST PATH (99% case):** Prompt text only (no flags): use defaults (count=1, service=gemini, style=photo, output=.claude/reports/images/), skip Steps 3-6 in Phase 1, go to config table (Step 7). AskUserQuestion only if API key missing.
>
> **AGENT INVOCATION:** Treat all provided args as final. AskUserQuestion only for truly missing values (prompt, API key). Config table still mandatory; confirmation step skippable if all params explicit.
> **API KEY PRIORITY** (first found wins):
> 1. Inline in `$ARGUMENTS`
> 2. `.env` in project root (`source .env 2>/dev/null`)
> 3. Shell environment variable
> 4. AskUserQuestion -> Phase C
>
> Display full resolved configuration table before any API call.
---
## Phase 0: Parse Arguments
**EXECUTE** using Bash tool:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/parse-args.sh" $ARGUMENTS && echo "OK" || echo "FAILED"
```
Output: KEY=VALUE pairs. Store all values. Scan `$ARGUMENTS` for inline API key or service/style mentions not captured by flags.
| Key | Default | Options |
|-----|---------|---------|
| `PROMPT` | (empty) | Free-text image description |
| `MODE` | generate | generate, edit, config, update |
| `SERVICE` | gemini | gemini, openrouter, openai |
| `STYLE` | photo | photo, illustration, art |
| `COUNT` | 1 | 1-10 |
| `OUTPUT` | .claude/reports/images/ | Directory path |
| `SIZE` | 1024x1024 | WxH format |
| `EDIT_IMAGE` | (empty) | Path to image for edit mode |
| `EDIT_INSTRUCTIONS` | (empty) | Edit instructions text |
| `PROMPT_MISSING` | false | true if no prompt in generate mode |
> **STOP if FAILED** -- check parse-args.sh output for error details.
Route by parsed MODE:
| Parsed MODE | Go to |
|-------------|-------|
| generate | Phase 1 |
| edit | Phase 1 |
| config | Phase C |
| update | Phase U |
---
## Phase 1: Validate and Gather
### Step 1: Load Environment and Check API Key
**EXECUTE** using Bash tool:
```bash
[ -f .env ] && set -a && . .env && set +a; bash "${CLAUDE_SKILL_DIR}/scripts/validate-key.sh" "SERVICE_HERE" && echo "OK" || echo "FAILED"
```
> **If FAILED:** Redirect to Phase C. Tell user: "No valid API key found for {SERVICE}. Let's configure it."
### Step 2: Gather Missing Parameters
If MODE=generate and PROMPT_MISSING=true, ask via AskUserQuestion: "What image do you need? Describe the scene, subject, and mood." Store response as PROMPT.
> **FAST PATH CHECK:** If PROMPT provided and no explicit --service/--style/--count/--output flags: skip Steps 3-6, jump to Step 7.
### Step 3: Confirm Image Count (skip on fast path)
**ASK** using AskUserQuestion: "How many images to generate?"
Options: "1 (default, fastest)" | "2-3 (compare variations)" | "4+ (batch generation, up to 10)"
> DALL-E 3 supports only 1 image per request. If SERVICE=openai and COUNT>1, generate COUNT sequential requests.
### Step 4: Confirm Service (skip on fast path)
**ASK** using AskUserQuestion: "Which image generation service?"
| Service | Model | Speed | Quality | Cost |
|---------|-------|-------|---------|------|
| openrouter | Gemini 2.5 Flash Image | Fast | High | ~$0.001/image |
| gemini | Imagen 4 | Fast | Very High | Paid plan required |
| openrouter-gpt5 | GPT-5 Image | Medium | Highest | ~$0.01/image |
| openai | DALL-E 3 | Medium | High | $0.04-0.12/image |
Options: "openrouter (cheapest, default)" | "gemini (Imagen 4)" | "openrouter-gpt5 (GPT-5)" | "openai (DALL-E 3)" | "Keep current: {SERVICE}"
Re-validate key if service changed.
### Step 5: Confirm Style (skip on fast path)
**ASK** using AskUserQuestion: "Image style?"
- photo: Physically accurate photography
- illustration: Professional illustration, clean line work
- art: Consistent artistic medium, unified brushwork
Options: "photo" | "illustration" | "art" | "Keep current: {STYLE}"
### Step 6: Confirm Output Directory (skip on fast path)
**ASK** using AskUserQuestion: "Where to save generated images?"
Options: ".claude/reports/images/ (default)" | "Current directory (.)" | "Custom path"
### Step 7: Display Resolved Configuration (MANDATORY)
```
=== Image Generation Config ===
| Parameter | Value |
|-----------|-------|
| Prompt | {PROMPT (first 80 chars)}... |
| Service | {SERVICE} ({model name}) |
| Style | {STYLE} |
| Count | {COUNT} |
| Size | {SIZE} |
| Output | {OUTPUT} |
| API Key | {first 8 chars}...{last 4 chars} |
| Est. Cost | {estimate based on service and count} |
================================
```
### Step 8: Final Confirmation
**ASK** using AskUserQuestion: "Proceed with generation?"
Options: "Yes, generate" | "No, change settings" | "Cancel"
> "change settings" -> Step 4. "Cancel" -> STOP.
---
## Phase 2: Build Payload and Generate
1. Read `${CLAUDE_SKILL_DIR}/references/anti-slop.md`. Extract section matching STYLE. Store as ANTI_SLOP_PREFIX.
2. Build: `ENHANCED_PROMPT = ANTI_SLOP_PREFIX + "\n\n" + PROMPT`
3. Read `${CLAUDE_SKILL_DIR}/references/providers.md`. Use section for resolved SERVICE to build JSON payload.
4. Construct JSON payload per `references/providers.md`. Insert ENHANCED_PROMPT, COUNT, SIZE.
**EXECUTE** using Bash tool:
```bash
cat > /tmp/image-gen-payload.json << 'PAYLOAD_EOF'
{JSON_PAYLOAD_HERE}
PAYLOAD_EOF
jq empty /tmp/image-gen-payload.json && echo "PAYLOAD_VALID" || echo "PAYLOAD_INVALID"
```
> **STOP if PAYLOAD_INVALID** -- fix JSON and retry.
**EXECUTE** using Bash tool:
```bash
[ -f .env ] && set -a && . .env && set +a; bash "${CLAUDE_SKILL_DIR}/scripts/api-request.sh" /tmp/image-gen-payload.json /tmp/image-gen-response.json "SERVICE_HERE" && echo "API_OK" || echo "API_FAILED"
```
> **If API_FAILED:** Check /tmp/image-gen-response.json. Rate limit (429) -> wait 30s, retry once. Content policy -> inform user, suggest rephrasing. Auth error (401/403) -> Phase C. Other -> show error, offer retry or cancel.
> For openai with COUNT>1: loop COUNT times, increment version in output filename.
Parse response by service:
| Service | Image location | Format |
|---------|---------------|--------|
| gemini | `predictions[].bytesBase64Encoded` | base64 PNG |
| openrouter | `data[].url` | URL to download |
| openai | `data[].url` or `data[].b64_json` | URL or base64 |
For base64 (gemini):
```bash
jq -r '.predictions[INDEX].bytesBase64Encoded' /tmp/image-gen-response.json > /tmp/image-gen-b64-INDEX.txt
```
---
## Phase 2E: Build Edit Payload (edit mode only)
**EXECUTE** using Bash tool:
```bash
EDIT_IMG="EDIT_IMAGE_PATH_HERE"
[ -f "$EDIT_IMG" ] && file --mime-type "$EDIT_IMG" | grep -qE ': image/' && echo "VALID_IMAGE" || echo "INVALID"
```
> If INVALID -> AskUserQuestion for correct path or cancel.
Read `${CLAUDE_SKILL_DIR}/references/mode-edit.md` for provider-specific edit payloads and endpoints.
Edit support: gemini (Yes), openrouter (No -- redirect user), openai (Yes via dall-e-2).
Construct edit payload per `references/mode-edit.md`. Same API call pattern as Phase 2.
---
## Phase 3: Save Images
Create kebab-case title from PROMPT (max 30 chars). Example: "a cozy coffee shop at sunset" -> "cozy-coffee-shop-sunset"
**EXECUTE** using Bash tool:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/save-image.sh" "SOURCE_HERE" "OUTPUT_DIR" "TITLE" "SERVICE" "PROMPT" "STYLE" "SIZE" && echo "SAVE_OK" || echo "SAVE_FAILED"
```
Replace: SOURCE_HERE (URL or temp file from Phase 2), OUTPUT_DIR, TITLE, SERVICE, PROMPT (original, not enhanced), STYLE, SIZE.
> **STOP if SAVE_FAILED** -- check stderr, offer retry.
---
## Phase 4: Report
Display table: file paths, sidecar JSON paths, provider, style, size, prompt (truncated), estimated cost.
Cost per image: gemini ~$0.02 (free tier), openrouter ~$0.04, openai $0.04-0.12.
**ASK** using AskUserQuestion: "What next?"
Options: "Generate more (same settings)" | "Different prompt" | "Edit one of these images" | "Done"
> "Generate more" -> Phase 2. "Different prompt" -> Phase 1 Step 2. "Edit" -> edit mode. "Done" -> STOP.
---
## Phase C: Config Mode
1. **ASK** which service: "openrouter" | "gemini" | "openrouter-gpt5" | "openai" | "All services"
2. **ASK** for API key. Key URLs: Gemini `https://aistudio.google.com/apikey`, OpenRouter `https://openrouter.ai/keys`, OpenAI `https://platform.openai.com/api-keys`
3. **EXECUTE** validate:
```bash
export SERVICE_KEY_HERE="USER_KEY_HERE"; bash "${CLAUDE_SKILL_DIR}/scripts/validate-key.sh" "SERVICE_HERE" && echo "KEY_VALID" || echo "KEY_INVALID"
```
> If KEY_INVALID -> show error, offer re-enter or skip.
4. **ASK** where to save: ".env in project root (default)" | "~/.zshrc (system-wide)" | ".claude.local.md (project-level)". For `.env`: ensure `.env` is in `.gitignore`.
5. **EXECUTE** verify:
```bash
[ -f .env ] && set -a && . .env && set +a; bash "${CLAUDE_SKILL_DIR}/scripts/validate-key.sh" "SERVICE_HERE" && echo "CONFIG_OK" || echo "CONFIG_FAILED"
```
---
## Phase U: Update Mode
1. **Research** via WebSearch: "Google Gemini Imagen API latest models 2026", "OpenRouter image generation API models 2026", "OpenAI DALL-E API latest models pricing 2026"
2. Read `${CLAUDE_SKILL_DIR}/references/providers.md`
3. Compare and report:
| Provider | Current Model | Latest Model | Pricing Change | Breaking Changes |
|----------|--------------|--------------|----------------|------------------|
| gemini | {current} | {latest} | {yes/no} | {details} |
| openrouter | {current} | {latest} | {yes/no} | {details} |
| openai | {current} | {latest} | {yes/no} | {details} |
4. If changes found, **ASK**: "Update references/providers.md?" Options: "Yes, update" | "Show details first" | "No, keep current". If Yes -> update `${CLAUDE_SKILL_DIR}/references/providers.md`.
</instructions>
@@ -1,86 +0,0 @@
# Anti-Slop Strategy
## Step 1: Story-First (before writing any prompt)
1. **Lore** — WHY are these objects/people in this scene? What caused this moment?
2. **Physics** — What physical laws govern this scene (gravity, light, materials)?
3. **Time** — What will happen in the next second? Scene is frozen, not static.
4. **Era** — What period is this? Name 3 things that must NOT appear (anachronisms).
5. **Prompt** — Only now write the prompt. Every element must be grounded above.
> "a programmer at a desk" → 2003 startup, 2am crunch → single desk lamp, monitor glow, coffee steam → just looked up → CRT monitor, tangled cables, sticky notes → no hologram, no glowing blue.
---
## Step 2: Replace Generic with Specific
| Instead of... | Use... |
|---|---|
| `dramatic lighting` | `single 40W desk lamp, warm tungsten, long shadow left` |
| `futuristic computer` | `IBM ThinkPad T42, lid open, screen reflecting on face` |
| `beautiful woman` | `30-year-old baker, flour on apron, tired eyes after 5am shift` |
| `epic landscape` | `Tuscan hillside, July, dried grass, heat haze at horizon` |
| `cinematic scene` | `35mm film grain, slightly underexposed, natural color cast` |
---
## Step 3: Forbidden Patterns (never generate these)
**Technology:** holographic UI panels, glowing blue circuits/server racks, portless sleek laptops (show cables/ports/vents), quantum computer aesthetics, data centers with teal glow
**Lighting:** god rays as filler, rim-light halo on every subject, lens flares without real source, multiple contradictory light sources, bioluminescent glow on skin/water/organisms
**Color:** teal+orange grading, purple/pink gradient backgrounds, neon on dark without falloff, blue glow on any object, oversaturated palette
**Abstract/Cosmic:** Earth glowing blue from space, neural networks as glowing nodes, glowing DNA/atoms, nebula as background filler, floating particles, energy fields, magic dust
**Composition:** subject dead-center + symmetrical, dramatic low-angle hero shot, person silhouetted against gradient, hands holding glowing orb, "epic cinematic" everything
**Textures:** plastic poreless skin, metallic sheen on non-metals, every surface polished and perfect, repetitive algorithmic patterns
---
## Step 4: Forbidden Keywords (never include in prompt)
Quality inflators: `masterpiece` `best quality` `ultra-detailed` `8k` `4k` `UHD` `hyperrealistic` `award-winning` `trending on ArtStation`
Style homogenizers: `cinematic` `epic` `dramatic` `futuristic` `sci-fi` `cyberpunk` `neon` `holographic` `glowing` `bioluminescent` `ethereal` `mystical`
CGI triggers: `octane render` `unreal engine` `ray tracing` `CGI` `concept art` `matte painting` `volumetric lighting` `global illumination` `subsurface scattering`
---
## Step 5: Style-Specific Constraints (prepend to prompt)
### photo
```
CONSTRAINTS — Physically accurate photography:
- Single coherent light source, correct shadow direction and softness
- Exactly 5 fingers per hand, proper proportions, natural skin texture
- Fabric wrinkles follow gravity, metal reflects environment, glass refracts
- No glow halos, no plastic skin, no floating objects, no impossible geometry
- No repeating tile textures, no fractal noise surfaces
- Proper depth of field, chromatic aberration at edges, subtle lens distortion
```
### illustration
```
CONSTRAINTS — Professional illustration quality:
- Clean intentional line work: consistent stroke weight, no wobbly artifacts
- Harmonious palette, intentional contrast, no random saturation spikes
- Slight organic imperfections welcome, NO perfect symmetry
- Single vanishing point or intentional isometric, never mixed
- Preserve texture and grain appropriate to medium
- Functional elements: doors have handles, cups have bases, chairs have four legs
```
### art
```
CONSTRAINTS — Consistent artistic medium:
- Single coherent medium: oil OR watercolor OR digital, never mixed unintentionally
- Rule of thirds or golden ratio, clear focal point
- Preserve brushstroke texture, canvas grain, paper tooth
- One light source direction throughout
- Gravity works, reflections accurate, shadows consistent
- Unified color temperature, no random neon in a muted palette
```
@@ -1,124 +0,0 @@
# Edit Mode Reference
Image editing via supported providers. Not all providers support editing.
## Provider Support
| Service | Edit support | Model | Endpoint |
|---------|-------------|-------|----------|
| gemini | Yes | imagen-4.0-generate-001 | Same base + `:predict` |
| openrouter | No | -- | -- |
| openai | Yes | dall-e-2 | `/v1/images/edits` |
If user selects openrouter for editing, redirect: "FLUX does not support image editing. Switch to gemini or openai."
## Gemini Edit
### Endpoint
`https://generativelanguage.googleapis.com/v1beta/models/imagen-4.0-generate-001:predict?key=GEMINI_API_KEY`
### Payload
```json
{
"instances": [
{
"prompt": "EDIT_INSTRUCTIONS",
"image": {
"bytesBase64Encoded": "BASE64_ENCODED_IMAGE"
}
}
],
"parameters": {
"sampleCount": 1,
"safetyFilterLevel": "block_few"
}
}
```
### Preparation
1. Read source image as base64:
```bash
base64 -i "IMAGE_PATH" | tr -d '\n' > /tmp/image-gen-edit-b64.txt
```
2. Build payload with base64 content inlined
3. Response format is identical to generate mode: `predictions[].bytesBase64Encoded`
### Image Size Limits
Gemini accepts images up to 20MB. If larger, resize first:
```bash
sips -Z 2048 "IMAGE_PATH" --out /tmp/image-gen-edit-resized.png
```
## OpenAI Edit (DALL-E 2)
### Endpoint
`https://api.openai.com/v1/images/edits`
### Request Format
Multipart form data (NOT JSON):
```bash
curl -X POST "https://api.openai.com/v1/images/edits" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F "model=dall-e-2" \
-F "image=@IMAGE_PATH" \
-F "prompt=EDIT_INSTRUCTIONS" \
-F "n=1" \
-F "size=1024x1024"
```
### Requirements
- Image must be PNG format
- Image must be square
- Image must be less than 4MB
- If image is not PNG/square, convert first:
```bash
sips -s format png -Z 1024 "IMAGE_PATH" --out /tmp/image-gen-edit-input.png
```
### Optional Mask
DALL-E 2 supports masking (transparent areas indicate where to edit):
```bash
curl -X POST "https://api.openai.com/v1/images/edits" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F "model=dall-e-2" \
-F "image=@IMAGE_PATH" \
-F "mask=@MASK_PATH" \
-F "prompt=EDIT_INSTRUCTIONS" \
-F "n=1" \
-F "size=1024x1024"
```
Mask must be same size PNG with transparent regions marking edit areas.
### Response Format
Same as DALL-E 3 generate: `data[].url`
## Edit Flow
```
1. Validate EDIT_IMAGE exists and is valid image
2. Check SERVICE supports editing
NO -> suggest gemini or openai
3. Read EDIT_INSTRUCTIONS
4. Prepare image (resize/convert if needed)
5. Build provider-specific edit payload
6. Send request
7. Parse response (same as generate)
8. Save with edit metadata in sidecar
```
## Edit Sidecar Metadata
The save-image.sh sidecar JSON should include extra fields for edits:
- `"type": "edit"`
- `"source_image": "original_image_path"`
- `"edit_instructions": "user edit text"`
@@ -1,103 +0,0 @@
# Generate Mode Reference
Full generate flow with decision trees, error handling, and retry logic.
## Decision Tree
```
PROMPT provided?
YES -> Validate SERVICE key
VALID -> Build payload -> Send -> Parse -> Save -> Report
INVALID -> Redirect to config mode
NO -> Ask user for prompt -> continue flow
```
## Payload Construction
### Gemini Imagen 3
1. Map SIZE to aspectRatio (see providers.md)
2. Clamp COUNT to 1-8 range
3. Build JSON:
```json
{
"instances": [{"prompt": "ANTI_SLOP_PREFIX\n\nUSER_PROMPT"}],
"parameters": {"sampleCount": N, "aspectRatio": "W:H", "safetyFilterLevel": "block_few"}
}
```
4. Write to `/tmp/image-gen-payload.json`
### OpenRouter FLUX
1. Validate SIZE is supported (1024x1024, 1024x768, 768x1024, 1536x1024, 1024x1536)
2. Clamp COUNT to 1-4 range
3. Build JSON:
```json
{
"model": "black-forest-labs/flux-1.1-pro",
"prompt": "ANTI_SLOP_PREFIX\n\nUSER_PROMPT",
"n": N,
"size": "WxH"
}
```
### OpenAI DALL-E 3
1. Map SIZE to nearest supported (1024x1024, 1024x1792, 1792x1024)
2. Force n=1 (hard API limit)
3. Build JSON:
```json
{
"model": "dall-e-3",
"prompt": "ANTI_SLOP_PREFIX\n\nUSER_PROMPT",
"n": 1,
"size": "WxH",
"quality": "hd",
"response_format": "url"
}
```
4. For COUNT>1: loop COUNT times with variation suffix
## Response Parsing
| Service | Extract | Type |
|---------|---------|------|
| gemini | `jq -r '.predictions[N].bytesBase64Encoded'` | base64 -> decode to file |
| openrouter | `jq -r '.data[N].url'` | URL -> download |
| openai | `jq -r '.data[0].url'` | URL -> download |
## Error Handling
| HTTP Code | Cause | Action |
|-----------|-------|--------|
| 400 | Bad request / invalid prompt | Show error, ask user to rephrase |
| 401 | Invalid API key | Redirect to Phase C (config) |
| 403 | Forbidden / content policy | Inform user, suggest rephrasing |
| 429 | Rate limited | Wait 30s, retry once. If still 429, inform user |
| 500-503 | Server error | Retry once after 10s. If persistent, try different provider |
### Content Policy Violations
All providers may reject prompts that violate content policies. If rejected:
1. Show the error message from the API
2. Suggest the user rephrase (remove violent/explicit/copyrighted content)
3. Offer to try a different provider (policies vary)
### Network Errors
If curl fails (timeout, DNS, connection refused):
1. Check internet connectivity
2. Retry once after 5s
3. If persistent, show error and offer to cancel or retry later
## Retry Logic
Maximum 2 retries per request. Delays:
- Rate limit (429): 30s between retries
- Server error (5xx): 10s between retries
- Network error: 5s between retries
After exhausting retries, show final error and offer:
- Try a different provider
- Save prompt for later retry
- Cancel
@@ -1,319 +0,0 @@
# Update Mode Protocol
Procedure for `--update` mode. Checks each provider for latest models, pricing changes, and API updates. Produces a comparison report and offers to update `providers.md`.
---
## Provider 1: OpenRouter
Current models: `google/gemini-2.5-flash-image`, `google/gemini-3.1-flash-image-preview`, `google/gemini-3-pro-image-preview`, `openai/gpt-5-image-mini`, `openai/gpt-5-image`
### Step 1: Fetch Model List
**EXECUTE** using Bash tool:
```bash
[ -f .env ] && set -a && . .env && set +a
curl -s "https://openrouter.ai/api/v1/models" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
| jq '[.data[] | select(
(.architecture.modality // "" | test("image"; "i"))
or (.name // "" | test("image|imagen|dall|flux|stable.diffusion|midjourney"; "i"))
or (.id // "" | test("image"; "i"))
) | {id, name, pricing: .pricing, context_length}]' \
> /tmp/openrouter-image-models.json \
&& echo "FETCHED $(jq length /tmp/openrouter-image-models.json) image models" \
|| echo "FETCH_FAILED"
```
> If FETCH_FAILED: check API key validity. Redirect to Phase C if 401/403.
### Step 2: Compare With Current
**EXECUTE** using Bash tool:
```bash
echo "=== Current OpenRouter models in providers.md ==="
echo " google/gemini-2.5-flash-image (default)"
echo " google/gemini-3.1-flash-image-preview"
echo " google/gemini-3-pro-image-preview"
echo " openai/gpt-5-image-mini"
echo " openai/gpt-5-image"
echo ""
echo "=== Available image models from API ==="
jq -r '.[] | " \(.id) -- \(.name) -- input: \(.pricing.prompt // "n/a") output: \(.pricing.completion // "n/a")"' /tmp/openrouter-image-models.json | sort
echo ""
echo "=== New models (not in current list) ==="
jq -r '.[].id' /tmp/openrouter-image-models.json | grep -vE "google/gemini-2.5-flash-image|google/gemini-3.1-flash-image-preview|google/gemini-3-pro-image-preview|openai/gpt-5-image-mini|openai/gpt-5-image" || echo " (none)"
echo ""
echo "=== Pricing for current models ==="
jq -r '.[] | select(.id == "google/gemini-2.5-flash-image" or .id == "openai/gpt-5-image" or .id == "openai/gpt-5-image-mini") | "\(.id): input=\(.pricing.prompt // "n/a") output=\(.pricing.completion // "n/a")"' /tmp/openrouter-image-models.json
```
### Step 3: Check Changelog
Use WebSearch:
```
"OpenRouter changelog image models {current_year}"
```
Direct URL: `https://openrouter.ai/docs/changelog`
Look for: new image-capable models added, models deprecated/removed, pricing tier changes, API breaking changes (response format, headers).
### Step 4: Record Findings
Store for final report:
- `openrouter_status`: OK or CHANGED
- `openrouter_current`: current default model
- `openrouter_latest`: latest recommended model
- `openrouter_pricing_changed`: yes/no
- `openrouter_notes`: free-text findings
---
## Provider 2: Google Gemini Imagen
Current model: `imagen-4.0-generate-001`
Also available: `imagen-4.0-ultra-generate-001`, `imagen-4.0-fast-generate-001`
### Step 1: List Models via API
**EXECUTE** using Bash tool:
```bash
[ -f .env ] && set -a && . .env && set +a
if [ -z "$GEMINI_API_KEY" ]; then
echo "SKIP_NO_KEY"
else
curl -s "https://generativelanguage.googleapis.com/v1beta/models?key=$GEMINI_API_KEY" \
| jq '[.models[] | select(.name | test("imagen")) | {name, displayName, description, supportedGenerationMethods}]' \
> /tmp/gemini-imagen-models.json \
&& echo "FETCHED" \
|| echo "FETCH_FAILED"
fi
```
### Step 2: Compare With Current
**EXECUTE** using Bash tool:
```bash
if [ -f /tmp/gemini-imagen-models.json ]; then
echo "=== Current Imagen models in providers.md ==="
echo " imagen-4.0-generate-001 (default)"
echo " imagen-4.0-ultra-generate-001"
echo " imagen-4.0-fast-generate-001"
echo ""
echo "=== Available Imagen models from API ==="
jq -r '.[] | " \(.name) -- \(.displayName // "n/a")"' /tmp/gemini-imagen-models.json
echo ""
echo "=== New models (not in current list) ==="
jq -r '.[].name' /tmp/gemini-imagen-models.json | sed 's|models/||' | grep -vE "imagen-4.0-generate-001|imagen-4.0-ultra-generate-001|imagen-4.0-fast-generate-001" || echo " (none)"
else
echo "No API data available (SKIP_NO_KEY or FETCH_FAILED)"
fi
```
### Step 3: Check Documentation
Use WebSearch:
```
"Google Gemini Imagen API latest models {current_year}"
```
Direct URL: `https://ai.google.dev/gemini-api/docs/image-generation`
Known progression: imagen-3 -> imagen-4 (current). Check for: imagen-5, new variants (e.g. imagen-4-turbo), endpoint changes (`/v1beta/` -> `/v1/`), new aspect ratios, new parameters.
### Step 4: Check Pricing
Use WebSearch:
```
"Google Gemini API pricing image generation {current_year}"
```
URL: `https://ai.google.dev/pricing`
Current: free tier available, ~$0.02/image beyond. Record changes.
### Step 5: Record Findings
Store: `gemini_status`, `gemini_current`, `gemini_latest`, `gemini_pricing_changed`, `gemini_notes`
---
## Provider 3: OpenAI DALL-E
Current model: `dall-e-3`
### Step 1: Check Models API
**EXECUTE** using Bash tool:
```bash
[ -f .env ] && set -a && . .env && set +a
if [ -z "$OPENAI_API_KEY" ]; then
echo "SKIP_NO_KEY"
else
curl -s "https://api.openai.com/v1/models" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
| jq '[.data[] | select(.id | test("dall|image|gpt.*image")) | {id, created, owned_by}]' \
> /tmp/openai-image-models.json \
&& echo "FETCHED" \
|| echo "FETCH_FAILED"
fi
```
### Step 2: Compare With Current
**EXECUTE** using Bash tool:
```bash
if [ -f /tmp/openai-image-models.json ]; then
echo "=== Current OpenAI models in providers.md ==="
echo " dall-e-3 (generate)"
echo " dall-e-2 (edit only)"
echo ""
echo "=== Available image models from API ==="
jq -r '.[] | " \(.id) -- owned_by: \(.owned_by) created: \(.created | todate)"' /tmp/openai-image-models.json
echo ""
echo "=== New models ==="
jq -r '.[].id' /tmp/openai-image-models.json | grep -vE "dall-e-3|dall-e-2" || echo " (none)"
else
echo "No API data available (SKIP_NO_KEY or FETCH_FAILED)"
fi
```
### Step 3: Check Documentation
Use WebSearch:
```
"OpenAI image generation API latest models {current_year}"
```
Direct URLs:
- `https://platform.openai.com/docs/guides/images`
- `https://platform.openai.com/docs/models`
Check for: DALL-E 4, GPT-Image (native, not via OpenRouter), new sizes, new quality tiers, `response_format` changes.
### Step 4: Check Pricing
Use WebSearch:
```
"OpenAI API pricing image generation {current_year}"
```
URL: `https://openai.com/api/pricing`
Current pricing:
- 1024x1024 standard: $0.04
- 1024x1024 HD: $0.08
- 1792x1024 HD: $0.12
Record any changes.
### Step 5: Record Findings
Store: `openai_status`, `openai_current`, `openai_latest`, `openai_pricing_changed`, `openai_notes`
---
## Provider 4: New Provider Discovery
### Step 1: Search for Emerging Providers
Use WebSearch (run both):
```
"AI image generation API {current_year} new providers"
```
```
"best AI image generation API comparison {current_year}"
```
### Step 2: Check OpenRouter for New Image Models
Review `/tmp/openrouter-image-models.json` (from Provider 1 Step 1) for models not from known providers (google, openai). Look for: Flux, Stable Diffusion 4+, Midjourney API, Ideogram, Recraft, other newcomers.
### Step 3: Evaluate Candidates
For each discovered provider, check against criteria:
| Criterion | Requirement |
|-----------|-------------|
| API access | Internationally accessible (no region lock) |
| Auth | API key auth (no OAuth complexity) |
| Quality | Comparable to DALL-E 3 or better |
| Pricing | Reasonable (under $0.15/image) |
| Stability | Public API, not alpha/waitlist |
| Integration | REST API with JSON payloads |
Record any candidates that pass all criteria.
---
## Report Generation
After completing all provider checks, output the comparison report.
### Format
```
=== Provider Update Report ({date}) ===
| Provider | Current Model | Latest Available | Pricing Change | Status |
|----------|--------------|-----------------|----------------|--------|
| openrouter | gemini-2.5-flash-image | {latest} | {yes/no/unknown} | {OK/CHANGED/DEPRECATED/ERROR} |
| gemini | imagen-4.0-generate-001 | {latest} | {yes/no/unknown} | {OK/CHANGED/DEPRECATED/ERROR} |
| openrouter-gpt5 | gpt-5-image | {latest} | {yes/no/unknown} | {OK/CHANGED/DEPRECATED/ERROR} |
| openai | dall-e-3 | {latest} | {yes/no/unknown} | {OK/CHANGED/DEPRECATED/ERROR} |
New providers discovered: {list or "none"}
Providers skipped (no API key): {list or "none"}
```
### Status Definitions
| Status | Meaning |
|--------|---------|
| OK | Model unchanged, pricing unchanged, API unchanged |
| CHANGED | New model version, pricing update, or API change detected |
| DEPRECATED | Current model no longer available or marked for removal |
| ERROR | Could not verify (API error, timeout, or no key) |
### Detail Section
For each provider with status != OK, include a detail block:
```
--- {provider} Details ---
Change type: {model_update / pricing_change / api_change / deprecation}
Current: {current model and pricing}
New: {new model and pricing}
Action required: {what to update in providers.md}
Breaking: {yes/no -- does the payload format or endpoint change?}
```
---
## Post-Report Actions
### If Changes Found
**ASK** using AskUserQuestion:
```
Changes detected in provider APIs. What would you like to do?
```
Options:
- "Update providers.md with all changes"
- "Update providers.md selectively (choose which)"
- "Show raw API data first"
- "No changes, keep current"
If updating: read `${CLAUDE_SKILL_DIR}/references/providers.md`, apply changes, write updated file. Preserve the existing document structure (sections, payload examples, response formats). Only update: model IDs, pricing values, size options, endpoint URLs, alt model lists.
### If No Changes
Output: "All providers are up to date. No changes needed."
### Cleanup
**EXECUTE** using Bash tool:
```bash
rm -f /tmp/openrouter-image-models.json /tmp/gemini-imagen-models.json /tmp/openai-image-models.json 2>/dev/null && echo "CLEANUP_OK"
```
@@ -1,87 +0,0 @@
# Prompt Engineering Guide
Tips for getting the best results from each provider.
## Provider Strengths
| Provider | Best at | Weak at |
|----------|---------|---------|
| Gemini Imagen 3 | Photorealism, landscapes, objects, text in images | Complex multi-person scenes |
| FLUX 1.1 Pro | Complex prompt following, text rendering, detailed scenes | Speed (slower than others) |
| DALL-E 3 | Artistic styles, creative interpretation, consistent quality | Exact prompt following (rewrites internally) |
## General Tips
### Lighting
Specify light source explicitly. "Soft golden hour sunlight from the left" beats "nice lighting". Mention shadows direction if important.
### Camera Angle
Use photography terms: "shot from below at 30 degrees", "bird's eye view", "eye-level medium shot", "close-up macro". Avoid vague "good angle".
### Background
Describe background separately from subject. "Subject X against a blurred bokeh city skyline at dusk" gives better results than "X in a city".
### Composition
Mention layout: "centered", "rule of thirds with subject on left", "negative space on right side for text overlay".
### Color Palette
Name specific colors or reference palettes: "muted earth tones", "high contrast black and gold", "pastel pink and sage green". Avoid "colorful" or "pretty colors".
## Provider-Specific Tips
### Gemini Imagen 3
- Excels at photorealistic scenes -- lean into real-world descriptions
- Good with product photography prompts ("product shot on marble surface, soft studio lighting")
- Handles landscapes well -- specify time of day, weather, season
- Text in images works reasonably well ("sign that reads 'OPEN'")
- For multiple objects, describe spatial relationships explicitly
### FLUX 1.1 Pro (OpenRouter)
- Best prompt follower -- include every detail you want
- Excellent text rendering -- can put legible text in images
- Handles complex scenes with many elements
- Specify exact counts: "three red apples" not "some apples"
- Style keywords work well: "in the style of vintage poster art"
- Negative prompts not supported -- describe what you WANT, not what you don't want
### DALL-E 3 (OpenAI)
- Rewrites your prompt internally -- check `revised_prompt` in response
- Very good at artistic/painterly styles
- Strong with conceptual/abstract imagery
- "Digital art", "oil painting", "watercolor" style keywords are well-calibrated
- Tends to add drama and detail beyond what you specify -- be explicit if you want minimalism
- For precise control, add "I NEED this exact scene:" before your prompt to reduce rewriting
## Anti-Slop Integration
The anti-slop prefixes (from `anti-slop.md`) are prepended automatically based on STYLE choice. They:
1. **photo** -- enforces physics accuracy, prevents AI glow/smoothing
2. **illustration** -- enforces clean linework, prevents symmetry artifacts
3. **art** -- enforces medium consistency, prevents mixed-media confusion
The prefix goes BEFORE the user prompt in the API payload. The model sees constraints first, then the creative prompt. This ordering matters -- constraints seen first are weighted more heavily.
## OG Image Tips
For blog/social OG images specifically:
- Size: 1200x630 (social preview) or 1200x675 (Twitter)
- Leave space for text overlay if adding title later
- Use high contrast -- images are shown as thumbnails
- Avoid fine detail that disappears at small size
- Dark backgrounds with bright accents work well for tech blogs
- Specify "clean, minimal composition with space for text overlay on the left third"
## Prompt Length
| Provider | Max prompt | Recommendation |
|----------|-----------|----------------|
| Gemini | ~1000 chars | 200-400 chars optimal |
| FLUX | ~2000 chars | 300-600 chars optimal |
| DALL-E 3 | 4000 chars | 200-500 chars (it rewrites anyway) |
Anti-slop prefix adds ~400 chars. Keep user prompt under 600 chars to stay within all limits.
@@ -1,187 +0,0 @@
# Provider Reference
API specs for each supported image generation provider. Use this to build correct payloads.
---
## Gemini Imagen 4
| Field | Value |
|-------|-------|
| Model | `imagen-4.0-generate-001` |
| Endpoint | `https://generativelanguage.googleapis.com/v1beta/models/imagen-4.0-generate-001:predict` |
| Auth | Query param: `?key=GEMINI_API_KEY` |
| Env var | `GEMINI_API_KEY` |
| Limits | 1-8 images per request |
| Cost | Free tier available, ~$0.02/image beyond |
| Also available | `imagen-4.0-ultra-generate-001` (ultra quality), `imagen-4.0-fast-generate-001` (fast) |
### Generate Payload
```json
{
"instances": [
{"prompt": "ENHANCED_PROMPT"}
],
"parameters": {
"sampleCount": COUNT,
"aspectRatio": "1:1",
"safetyFilterLevel": "block_few"
}
}
```
### Aspect Ratio Mapping
| Size | aspectRatio |
|------|-------------|
| 1024x1024 | 1:1 |
| 1024x768 | 4:3 |
| 768x1024 | 3:4 |
| 1280x720 | 16:9 |
| 720x1280 | 9:16 |
### Response Format
```json
{
"predictions": [
{"bytesBase64Encoded": "iVBOR...base64data...", "mimeType": "image/png"}
]
}
```
Extract: `predictions[N].bytesBase64Encoded` -> decode from base64 to PNG file.
---
## OpenRouter (Chat-based Image Generation)
| Field | Value |
|-------|-------|
| Default model | `google/gemini-2.5-flash-image` |
| Alt models | `google/gemini-3.1-flash-image-preview`, `google/gemini-3-pro-image-preview`, `openai/gpt-5-image-mini`, `openai/gpt-5-image` |
| Endpoint | `https://openrouter.ai/api/v1/chat/completions` |
| Auth | Header: `Authorization: Bearer $OPENROUTER_API_KEY` |
| Env var | `OPENROUTER_API_KEY` |
| Headers | `HTTP-Referer: https://brewcode.app`, `X-Title: brewcode-image-gen` |
| Limits | 1 image per request |
| Cost | ~$0.001-0.01/image (varies by model) |
| Edit support | No |
### Generate Payload
```json
{
"model": "google/gemini-2.5-flash-image",
"messages": [
{"role": "user", "content": "Generate an image: ENHANCED_PROMPT"}
]
}
```
### Response Format
```json
{
"choices": [
{
"message": {
"content": "text description...",
"images": [
{"type": "image_url", "image_url": {"url": "data:image/png;base64,iVBOR..."}}
]
}
}
]
}
```
Extract: `choices[0].message.images[N].image_url.url` -> strip `data:image/png;base64,` prefix -> decode base64 to PNG.
---
## OpenAI DALL-E 3
| Field | Value |
|-------|-------|
| Model | `dall-e-3` |
| Endpoint | `https://api.openai.com/v1/images/generations` |
| Auth | Header: `Authorization: Bearer $OPENAI_API_KEY` |
| Env var | `OPENAI_API_KEY` |
| Limits | 1 image per request (DALL-E 3 hard limit) |
| Cost | $0.04 (1024x1024 standard), $0.08 (1024x1024 HD), $0.12 (1792x1024 HD) |
| Edit model | `dall-e-2` via `/v1/images/edits` |
### Generate Payload
```json
{
"model": "dall-e-3",
"prompt": "ENHANCED_PROMPT",
"n": 1,
"size": "1024x1024",
"quality": "hd",
"response_format": "url"
}
```
### Size Options
`1024x1024`, `1024x1792`, `1792x1024`
DALL-E 3 only supports these three sizes. Map other sizes to nearest.
### Response Format
```json
{
"data": [
{"url": "https://...generated-image-url...", "revised_prompt": "..."}
]
}
```
Extract: `data[N].url` -> download via curl. Note: `revised_prompt` shows how DALL-E 3 rewrote the prompt internally.
### Multiple Images Workaround
DALL-E 3 returns exactly 1 image per request. For COUNT>1, make COUNT sequential requests. Append index to prompt variation: add "(variation N of COUNT)" to reduce identical outputs.
---
## OpenRouter GPT-5 Image (service: `openrouter-gpt5`)
| Field | Value |
|-------|-------|
| Model | `openai/gpt-5-image` |
| Endpoint | `https://openrouter.ai/api/v1/chat/completions` |
| Auth | Header: `Authorization: Bearer $OPENROUTER_API_KEY` |
| Env var | `OPENROUTER_API_KEY` (same key as openrouter) |
| Headers | `HTTP-Referer: https://brewcode.app`, `X-Title: brewcode-image-gen` |
| Limits | 1 image per request |
| Cost | ~$0.01/image (highest quality tier) |
| Edit support | No |
| Budget | High cost — confirm with user before batch generation |
### Generate Payload
```json
{
"model": "openai/gpt-5-image",
"messages": [
{"role": "user", "content": "Generate an image: ENHANCED_PROMPT"}
]
}
```
### Response Format
Same as OpenRouter (chat-based): `choices[0].message.images[N].image_url.url` -> strip `data:image/png;base64,` prefix -> decode base64 to PNG.
### Budget Controls
GPT-5 Image is the most expensive option. Skill MUST:
- Show estimated cost before generation
- For COUNT>1: warn user about total cost
- Default to `openrouter` (Gemini 2.5 Flash) unless user explicitly requests GPT-5
@@ -1,94 +0,0 @@
#!/bin/sh
# api-request.sh — HTTP transport with provider routing for image generation
# Usage: api-request.sh <payload.json> <output.json> <service>
# Env vars: GEMINI_API_KEY, OPENROUTER_API_KEY, OPENAI_API_KEY
# Output: raw API response saved to output.json, status info to stderr
set -e
PAYLOAD="${1:?Usage: api-request.sh <payload.json> <output.json> <service>}"
OUTPUT="${2:?Usage: api-request.sh <payload.json> <output.json> <service>}"
SERVICE="${3:?Usage: api-request.sh <payload.json> <output.json> <service>}"
[ -f "$PAYLOAD" ] || { echo "ERROR: Payload not found: $PAYLOAD" >&2; exit 1; }
jq empty "$PAYLOAD" 2>/dev/null || { echo "ERROR: Invalid JSON in $PAYLOAD" >&2; exit 1; }
case "$SERVICE" in
gemini)
API_KEY="${GEMINI_API_KEY:?ERROR: GEMINI_API_KEY not set}"
API_URL="https://generativelanguage.googleapis.com/v1beta/models/imagen-4.0-generate-001:predict?key=$API_KEY"
echo "Sending to Gemini Imagen 4 ($API_URL)..." >&2
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$OUTPUT" \
--retry 3 --retry-delay 5 --retry-max-time 60 \
--max-time 120 \
-X POST "$API_URL" \
-H "Content-Type: application/json" \
-d @"$PAYLOAD")
;;
openrouter)
API_KEY="${OPENROUTER_API_KEY:?ERROR: OPENROUTER_API_KEY not set}"
API_URL="https://openrouter.ai/api/v1/chat/completions"
echo "Sending to OpenRouter ($API_URL)..." >&2
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$OUTPUT" \
--retry 3 --retry-delay 5 --retry-max-time 60 \
--max-time 120 \
-X POST "$API_URL" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "HTTP-Referer: https://brewcode.app" \
-H "X-Title: brewcode-image-gen" \
-d @"$PAYLOAD")
;;
openrouter-gpt5)
API_KEY="${OPENROUTER_API_KEY:?ERROR: OPENROUTER_API_KEY not set}"
API_URL="https://openrouter.ai/api/v1/chat/completions"
echo "Sending to OpenRouter GPT-5 Image ($API_URL)..." >&2
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$OUTPUT" \
--retry 3 --retry-delay 5 --retry-max-time 60 \
--max-time 120 \
-X POST "$API_URL" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "HTTP-Referer: https://brewcode.app" \
-H "X-Title: brewcode-image-gen" \
-d @"$PAYLOAD")
;;
openai)
API_KEY="${OPENAI_API_KEY:?ERROR: OPENAI_API_KEY not set}"
API_URL="https://api.openai.com/v1/images/generations"
echo "Sending to OpenAI DALL-E 3 ($API_URL)..." >&2
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$OUTPUT" \
--retry 3 --retry-delay 5 --retry-max-time 60 \
--max-time 120 \
-X POST "$API_URL" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d @"$PAYLOAD")
;;
*)
echo "ERROR: Unknown service: $SERVICE (use: gemini, openrouter, openrouter-gpt5, openai)" >&2
exit 1
;;
esac
echo "HTTP: $HTTP_CODE" >&2
if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 300 ]; then
echo "ERROR: API returned HTTP $HTTP_CODE" >&2
cat "$OUTPUT" >&2
exit 1
fi
if jq -e '.error' "$OUTPUT" >/dev/null 2>&1; then
echo "ERROR: API error in response:" >&2
jq '.error' "$OUTPUT" >&2
exit 1
fi
RESP_SIZE=$(wc -c < "$OUTPUT" | tr -d ' ')
echo "Response saved: $OUTPUT ($RESP_SIZE bytes)" >&2
@@ -1,121 +0,0 @@
#!/bin/sh
# parse-args.sh — Parse image-gen skill arguments
# Usage: parse-args.sh [args...]
# Output: KEY=VALUE pairs to stdout
set -e
PROMPT=""
MODE="generate"
SERVICE="openrouter"
STYLE="photo"
COUNT="1"
OUTPUT=".claude/reports/images/"
SIZE="1024x1024"
EDIT_IMAGE=""
EDIT_INSTRUCTIONS=""
while [ $# -gt 0 ]; do
case "$1" in
--edit)
MODE="edit"
EDIT_IMAGE="${2:?--edit requires <image_path> <instructions>}"
EDIT_INSTRUCTIONS="${3:?--edit requires <image_path> <instructions>}"
shift 3
;;
--config)
MODE="config"
shift
;;
--update)
MODE="update"
shift
;;
--service|-s)
SERVICE="${2:?--service requires value: gemini|openrouter|openai}"
shift 2
;;
--style)
STYLE="${2:?--style requires value: photo|illustration|art}"
shift 2
;;
--count|-n)
COUNT="${2:?--count requires value: 1-10}"
shift 2
;;
--output|-o)
OUTPUT="${2:?--output requires value: directory path}"
shift 2
;;
--size)
SIZE="${2:?--size requires value: WxH format}"
shift 2
;;
--*)
echo "WARNING: Unknown flag: $1" >&2
shift
;;
*)
if [ -z "$PROMPT" ]; then
PROMPT="$1"
else
PROMPT="$PROMPT $1"
fi
shift
;;
esac
done
# Validate service
case "$SERVICE" in
gemini|openrouter|openrouter-gpt5|openai) ;;
*) echo "ERROR: Invalid service: $SERVICE (use: gemini, openrouter, openrouter-gpt5, openai)" >&2; exit 1 ;;
esac
# Validate style
case "$STYLE" in
photo|illustration|art) ;;
*) echo "ERROR: Invalid style: $STYLE (use: photo, illustration, art)" >&2; exit 1 ;;
esac
# Validate count is 1-10
if [ "$COUNT" -lt 1 ] 2>/dev/null || [ "$COUNT" -gt 10 ] 2>/dev/null; then
echo "ERROR: Invalid count: $COUNT (must be 1-10)" >&2
exit 1
fi
case "$COUNT" in
[1-9]|10) ;;
*) echo "ERROR: Invalid count: $COUNT (must be integer 1-10)" >&2; exit 1 ;;
esac
# Validate size format (WxH)
case "$SIZE" in
*x*)
WIDTH="${SIZE%%x*}"
HEIGHT="${SIZE#*x}"
case "$WIDTH" in
''|*[!0-9]*) echo "ERROR: Invalid size width: $SIZE (use WxH format, e.g. 1024x1024)" >&2; exit 1 ;;
esac
case "$HEIGHT" in
''|*[!0-9]*) echo "ERROR: Invalid size height: $SIZE (use WxH format, e.g. 1024x1024)" >&2; exit 1 ;;
esac
;;
*) echo "ERROR: Invalid size format: $SIZE (use WxH format, e.g. 1024x1024)" >&2; exit 1 ;;
esac
echo "PROMPT=$PROMPT"
echo "MODE=$MODE"
echo "SERVICE=$SERVICE"
echo "STYLE=$STYLE"
echo "COUNT=$COUNT"
echo "OUTPUT=$OUTPUT"
echo "SIZE=$SIZE"
echo "EDIT_IMAGE=$EDIT_IMAGE"
echo "EDIT_INSTRUCTIONS=$EDIT_INSTRUCTIONS"
if [ -z "$PROMPT" ] && [ "$MODE" = "generate" ]; then
echo "PROMPT_MISSING=true"
echo "NOTE: No prompt provided. Will ask user." >&2
else
echo "PROMPT_MISSING=false"
fi
@@ -1,111 +0,0 @@
#!/bin/sh
# save-image.sh — Download/decode image and create metadata sidecar
# Usage: save-image.sh <source> <output_dir> <title> <service> <prompt> [style] [size]
# Source: URL (http...), base64 file path, or image file path
# Output: saved file path to stdout
set -e
SOURCE="${1:?Usage: save-image.sh <source> <output_dir> <title> <service> <prompt> [style] [size]}"
OUTPUT_DIR="${2:?Usage: save-image.sh <source> <output_dir> <title> <service> <prompt> [style] [size]}"
TITLE="${3:?Usage: save-image.sh <source> <output_dir> <title> <service> <prompt> [style] [size]}"
SERVICE="${4:?Usage: save-image.sh <source> <output_dir> <title> <service> <prompt> [style] [size]}"
PROMPT="${5:?Usage: save-image.sh <source> <output_dir> <title> <service> <prompt> [style] [size]}"
STYLE="${6:-}"
SIZE="${7:-1024x1024}"
# Platform detection for base64
OS=$(uname -s)
case "$OS" in
Darwin) BASE64_DECODE="base64 -D" ;;
*) BASE64_DECODE="base64 -d" ;;
esac
# Map service to model name
case "$SERVICE" in
gemini) MODEL_NAME="imagen-4.0-generate-001" ;;
openrouter) MODEL_NAME="gemini-2.5-flash-image" ;;
openrouter-gpt5) MODEL_NAME="gpt-5-image" ;;
openai) MODEL_NAME="dall-e-3" ;;
*) MODEL_NAME="unknown" ;;
esac
# Create output directory
mkdir -p "$OUTPUT_DIR"
# Generate title in kebab-case, max 30 chars
SAFE_TITLE=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//' | sed 's/-$//')
SAFE_TITLE=$(echo "$SAFE_TITLE" | cut -c1-30 | sed 's/-$//')
# Generate timestamp
TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
# Auto-increment version
VERSION=1
while true; do
FILENAME="${TIMESTAMP}_${SAFE_TITLE}_${SERVICE}_v${VERSION}.png"
FILEPATH="${OUTPUT_DIR}/${FILENAME}"
if [ ! -f "$FILEPATH" ]; then
break
fi
VERSION=$((VERSION + 1))
done
# Acquire image based on source type
case "$SOURCE" in
http://*)
echo "Downloading image from URL..." >&2
curl -s -L --max-time 60 -o "$FILEPATH" "$SOURCE" || { echo "ERROR: Failed to download: $SOURCE" >&2; exit 1; }
;;
https://*)
echo "Downloading image from URL..." >&2
curl -s -L --max-time 60 -o "$FILEPATH" "$SOURCE" || { echo "ERROR: Failed to download: $SOURCE" >&2; exit 1; }
;;
*)
if [ ! -f "$SOURCE" ]; then
echo "ERROR: Source file not found: $SOURCE" >&2
exit 1
fi
# Detect binary image vs base64 text via magic bytes
HEADER=$(head -c 4 "$SOURCE" | od -A n -t x1 | tr -d ' ')
if echo "$HEADER" | grep -qE '^(89504e47|ffd8ff)'; then
echo "Copying image file..." >&2
cp "$SOURCE" "$FILEPATH"
else
echo "Decoding base64 image..." >&2
$BASE64_DECODE < "$SOURCE" > "$FILEPATH" || { echo "ERROR: Failed to decode base64 from: $SOURCE" >&2; exit 1; }
fi
;;
esac
# Verify the output file was created and is non-empty
if [ ! -s "$FILEPATH" ]; then
echo "ERROR: Output file is empty: $FILEPATH" >&2
exit 1
fi
# Generate ISO 8601 timestamp
ISO_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Create metadata sidecar JSON
SIDECAR="${FILEPATH%.png}.json"
# Escape prompt for JSON (handle quotes and backslashes)
ESCAPED_PROMPT=$(printf '%s' "$PROMPT" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g')
cat > "$SIDECAR" <<ENDJSON
{
"prompt": "$ESCAPED_PROMPT",
"provider": "$SERVICE",
"model": "$MODEL_NAME",
"style": "$STYLE",
"timestamp": "$ISO_TIMESTAMP",
"filename": "$FILENAME",
"size": "$SIZE"
}
ENDJSON
echo "Metadata saved: $SIDECAR" >&2
# Print saved file path to stdout
echo "$FILEPATH"
@@ -1,66 +0,0 @@
#!/bin/sh
# validate-key.sh — Test API key validity per provider
# Usage: validate-key.sh <service>
# Output: VALID or INVALID: <reason> to stdout
# Exit: 0 on valid, 1 on invalid
set -e
SERVICE="${1:?Usage: validate-key.sh <service> (gemini|openrouter|openrouter-gpt5|openai)}"
fail() {
echo "INVALID: $1"
exit 1
}
case "$SERVICE" in
gemini)
[ -n "${GEMINI_API_KEY:-}" ] || fail "GEMINI_API_KEY is not set"
RESPONSE=$(curl -s -w "\n%{http_code}" \
"https://generativelanguage.googleapis.com/v1beta/models?key=$GEMINI_API_KEY" \
--max-time 10) || fail "Connection failed to Gemini API"
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
BODY=$(echo "$RESPONSE" | sed '$d')
[ "$HTTP_CODE" = "200" ] || fail "HTTP $HTTP_CODE from Gemini API"
echo "$BODY" | grep -q '"models"' || fail "Unexpected response from Gemini API (no models field)"
echo "VALID"
;;
openrouter)
[ -n "${OPENROUTER_API_KEY:-}" ] || fail "OPENROUTER_API_KEY is not set"
RESPONSE=$(curl -s -w "\n%{http_code}" \
"https://openrouter.ai/api/v1/models" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
--max-time 10) || fail "Connection failed to OpenRouter API"
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
[ "$HTTP_CODE" = "200" ] || fail "HTTP $HTTP_CODE from OpenRouter API"
echo "VALID"
;;
openrouter-gpt5)
[ -n "${OPENROUTER_API_KEY:-}" ] || fail "OPENROUTER_API_KEY is not set"
RESPONSE=$(curl -s -w "\n%{http_code}" \
"https://openrouter.ai/api/v1/models" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
--max-time 10) || fail "Connection failed to OpenRouter API"
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
[ "$HTTP_CODE" = "200" ] || fail "HTTP $HTTP_CODE from OpenRouter API"
echo "VALID"
;;
openai)
[ -n "${OPENAI_API_KEY:-}" ] || fail "OPENAI_API_KEY is not set"
RESPONSE=$(curl -s -w "\n%{http_code}" \
"https://api.openai.com/v1/models" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
--max-time 10) || fail "Connection failed to OpenAI API"
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
[ "$HTTP_CODE" = "200" ] || fail "HTTP $HTTP_CODE from OpenAI API"
echo "VALID"
;;
*)
echo "ERROR: Unknown service: $SERVICE (use: gemini, openrouter, openrouter-gpt5, openai)" >&2
exit 1
;;
esac
@@ -1,158 +0,0 @@
# E2E Test Plan: image-gen skill — Generate Flow
Manual verification checklist for all modes of the image-gen skill.
## Prerequisites
- [ ] At least one API key is configured for a supported provider:
- `GEMINI_API_KEY` — for `gemini` (default)
- `OPENROUTER_API_KEY` — for `openrouter`
- `OPENAI_API_KEY` — for `openai`
- [ ] The skill is installed and accessible via `/image-gen` command in Claude Code
- [ ] `curl` and `base64` are available in the shell environment
- [ ] Working internet connection for API calls
---
## Scenario 1: Generate mode (default)
**Test 1.1 — Basic generate with default provider (gemini)**
Steps:
1. Run `/image-gen "a dark cozy workspace with mechanical keyboard"`
Expected:
- [ ] API call is made to Gemini Imagen
- [ ] Image file is saved to `.claude/reports/images/`
- [ ] Filename follows pattern: `YYYYMMDD-HHMMSS_a-dark-cozy-workspace_gemini_v1.png`
- [ ] JSON sidecar file exists next to the PNG with matching name
- [ ] Sidecar contains: `prompt`, `provider`, `model`, `timestamp`, `filename`, `style`, `size`
- [ ] Saved path is printed in the response
**Test 1.2 — Generate with explicit provider and style**
Steps:
1. Run `/image-gen --service openai --style art "neon city at night"`
Expected:
- [ ] API call is made to OpenAI DALL-E 3
- [ ] Filename contains `_openai_v1.png`
- [ ] Sidecar `model` field equals `dall-e-3`
- [ ] Sidecar `style` field equals `art`
**Test 1.3 — Generate with count > 1**
Steps:
1. Run `/image-gen --count 3 "abstract mountains"`
Expected:
- [ ] 3 PNG files are saved
- [ ] Files are numbered v1, v2, v3
- [ ] 3 corresponding JSON sidecars exist
**Test 1.4 — Generate with custom output directory**
Steps:
1. Run `/image-gen --output /tmp/my-images "a minimalist logo"`
Expected:
- [ ] `/tmp/my-images/` directory is created if it did not exist
- [ ] PNG and JSON files saved inside `/tmp/my-images/`
**Test 1.5 — Generate with custom size**
Steps:
1. Run `/image-gen --size 1792x1024 "wide landscape panorama"`
Expected:
- [ ] API request includes the specified size
- [ ] Sidecar `size` field equals `1792x1024`
---
## Scenario 2: Edit mode
**Test 2.1 — Edit an existing image**
Prerequisites: have a local image file at `/tmp/source.png`
Steps:
1. Run `/image-gen --edit /tmp/source.png "add warm golden glow to the background"`
Expected:
- [ ] API call uses edit/inpainting endpoint
- [ ] Result image saved with `_v1.png` suffix
- [ ] MODE is `edit` (visible in debug output or sidecar)
- [ ] EDIT_INSTRUCTIONS captured correctly in metadata
---
## Scenario 3: Config mode
**Test 3.1 — Show configuration**
Steps:
1. Run `/image-gen --config`
Expected:
- [ ] No image is generated
- [ ] Current configuration is displayed: default provider, style, output dir
- [ ] API keys presence is reported (masked or indicated as set/unset)
---
## Scenario 4: Update mode
**Test 4.1 — Update the skill**
Steps:
1. Run `/image-gen --update`
Expected:
- [ ] Skill update process is triggered
- [ ] No image is generated
- [ ] Confirmation message or version info displayed
---
## Scenario 5: Error handling
**Test 5.1 — Invalid API key**
Steps:
1. Set `GEMINI_API_KEY=invalid_key_value`
2. Run `/image-gen "test prompt"`
Expected:
- [ ] Error message indicates authentication failure
- [ ] No partial image file is left behind
- [ ] Exit with non-zero code
**Test 5.2 — No API key set**
Steps:
1. Unset all API keys
2. Run `/image-gen "test prompt"`
Expected:
- [ ] Error or prompt to configure a key
- [ ] No crash or unhandled error
**Test 5.3 — Invalid arguments**
Steps:
1. Run `/image-gen --service badprovider "test"`
Expected:
- [ ] Exit 1 with descriptive error message
- [ ] Message includes valid provider names
---
## Verification Checklist (run after all scenarios)
- [ ] All generated PNG files open correctly in an image viewer
- [ ] All sidecar JSON files are valid JSON (validate with `python3 -m json.tool <file>`)
- [ ] No temporary files left in `/tmp/` or project root
- [ ] Naming convention is consistent across all test outputs
- [ ] Log/error output goes to stderr, file paths go to stdout
@@ -1,132 +0,0 @@
#!/bin/sh
# test-parse-args.sh — Unit tests for parse-args.sh
# GIVEN/WHEN/THEN pattern: run parse-args.sh with args, grep output for expected KEY=VALUE
set -e
SCRIPT="$(dirname "$0")/../scripts/parse-args.sh"
PASS=0
FAIL=0
pass() {
printf 'PASS: %s\n' "$1"
PASS=$((PASS + 1))
}
fail() {
printf 'FAIL: %s\n %s\n' "$1" "$2"
FAIL=$((FAIL + 1))
}
assert_kv() {
# assert_kv <test_name> <output> <key> <expected_value>
TEST_NAME="$1"
OUTPUT="$2"
KEY="$3"
EXPECTED="$4"
ACTUAL=$(printf '%s\n' "$OUTPUT" | grep "^${KEY}=" | cut -d= -f2-)
if [ "$ACTUAL" = "$EXPECTED" ]; then
pass "$TEST_NAME: $KEY=$EXPECTED"
else
fail "$TEST_NAME: $KEY" "expected='$EXPECTED' actual='$ACTUAL'"
fi
}
assert_exit_nonzero() {
TEST_NAME="$1"
shift
if sh "$SCRIPT" "$@" >/dev/null 2>&1; then
fail "$TEST_NAME" "expected exit 1 but exited 0"
else
pass "$TEST_NAME"
fi
}
# --- Test 1: Simple prompt ---
# GIVEN a single positional argument
# WHEN parse-args.sh runs
# THEN PROMPT and MODE and PROMPT_MISSING are set correctly
OUT=$(sh "$SCRIPT" "a dark workspace" 2>/dev/null)
assert_kv "TC1 simple prompt: PROMPT" "$OUT" "PROMPT" "a dark workspace"
assert_kv "TC1 simple prompt: MODE" "$OUT" "MODE" "generate"
assert_kv "TC1 simple prompt: PROMPT_MISSING" "$OUT" "PROMPT_MISSING" "false"
# --- Test 2: Flags --service --style --count ---
# GIVEN flags --service openai --style art --count 3 and a prompt
# WHEN parse-args.sh runs
# THEN SERVICE, STYLE, COUNT are set to the given values
OUT=$(sh "$SCRIPT" --service openai --style art --count 3 "a city" 2>/dev/null)
assert_kv "TC2 flags: SERVICE" "$OUT" "SERVICE" "openai"
assert_kv "TC2 flags: STYLE" "$OUT" "STYLE" "art"
assert_kv "TC2 flags: COUNT" "$OUT" "COUNT" "3"
# --- Test 3: Edit mode ---
# GIVEN --edit <image_path> <instructions>
# WHEN parse-args.sh runs
# THEN MODE=edit, EDIT_IMAGE and EDIT_INSTRUCTIONS are set
OUT=$(sh "$SCRIPT" --edit /tmp/img.png "add glow" 2>/dev/null)
assert_kv "TC3 edit mode: MODE" "$OUT" "MODE" "edit"
assert_kv "TC3 edit mode: EDIT_IMAGE" "$OUT" "EDIT_IMAGE" "/tmp/img.png"
assert_kv "TC3 edit mode: EDIT_INSTRUCTIONS" "$OUT" "EDIT_INSTRUCTIONS" "add glow"
# --- Test 4: Config mode ---
# GIVEN --config flag
# WHEN parse-args.sh runs
# THEN MODE=config
OUT=$(sh "$SCRIPT" --config 2>/dev/null)
assert_kv "TC4 config mode: MODE" "$OUT" "MODE" "config"
# --- Test 5: Update mode ---
# GIVEN --update flag
# WHEN parse-args.sh runs
# THEN MODE=update
OUT=$(sh "$SCRIPT" --update 2>/dev/null)
assert_kv "TC5 update mode: MODE" "$OUT" "MODE" "update"
# --- Test 6: No args → PROMPT_MISSING=true ---
# GIVEN no arguments
# WHEN parse-args.sh runs
# THEN PROMPT_MISSING=true
OUT=$(sh "$SCRIPT" 2>/dev/null)
assert_kv "TC6 no args: PROMPT_MISSING" "$OUT" "PROMPT_MISSING" "true"
# --- Test 7: Invalid service → exit 1 ---
# GIVEN --service invalid
# WHEN parse-args.sh runs
# THEN exit code is non-zero
assert_exit_nonzero "TC7 invalid service" --service invalid "test"
# --- Test 8: Invalid style → exit 1 ---
# GIVEN --style nope
# WHEN parse-args.sh runs
# THEN exit code is non-zero
assert_exit_nonzero "TC8 invalid style" --style nope "test"
# --- Test 9: Count out of range → exit 1 ---
# GIVEN --count 15
# WHEN parse-args.sh runs
# THEN exit code is non-zero
assert_exit_nonzero "TC9 count out of range" --count 15 "test"
# --- Test 10: Output flag ---
# GIVEN --output /tmp/custom and a prompt
# WHEN parse-args.sh runs
# THEN OUTPUT=/tmp/custom
OUT=$(sh "$SCRIPT" --output /tmp/custom "test" 2>/dev/null)
assert_kv "TC10 output flag: OUTPUT" "$OUT" "OUTPUT" "/tmp/custom"
# --- Test 11: Size flag ---
# GIVEN --size 1280x720 and a prompt
# WHEN parse-args.sh runs
# THEN SIZE=1280x720
OUT=$(sh "$SCRIPT" --size 1280x720 "test" 2>/dev/null)
assert_kv "TC11 size flag: SIZE" "$OUT" "SIZE" "1280x720"
# --- Summary ---
TOTAL=$((PASS + FAIL))
printf '\n=== RESULTS: %d/%d passed ===\n' "$PASS" "$TOTAL"
if [ "$FAIL" -gt 0 ]; then
printf 'FAILED: %d test(s) failed\n' "$FAIL"
exit 1
fi
exit 0
@@ -1,167 +0,0 @@
#!/bin/sh
# test-save-image.sh — Unit tests for save-image.sh
# GIVEN/WHEN/THEN pattern: invoke save-image.sh, inspect outputs and filesystem artifacts
set -e
SCRIPT="$(dirname "$0")/../scripts/save-image.sh"
WORK_DIR="/tmp/image-gen-tests"
PASS=0
FAIL=0
# Tiny 1x1 valid PNG as base64 (single-pixel transparent PNG)
PNG_B64="iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
pass() {
printf 'PASS: %s\n' "$1"
PASS=$((PASS + 1))
}
fail() {
printf 'FAIL: %s\n %s\n' "$1" "$2"
FAIL=$((FAIL + 1))
}
setup() {
rm -rf "$WORK_DIR"
mkdir -p "$WORK_DIR"
# Write test base64 file once
printf '%s' "$PNG_B64" > "$WORK_DIR/test-b64.txt"
}
setup
# --- Test 1: No args → exit 1 with usage message ---
# GIVEN no arguments
# WHEN save-image.sh runs
# THEN exit code is non-zero
if sh "$SCRIPT" >/dev/null 2>&1; then
fail "TC1 no args" "expected exit 1 but exited 0"
else
pass "TC1 no args: exits non-zero"
fi
# --- Test 2: Create from base64 file → creates PNG + JSON sidecar ---
# GIVEN a valid base64-encoded PNG file as source
# WHEN save-image.sh runs with output dir, title, service, and prompt
# THEN a PNG file and a JSON sidecar are created
OUT_DIR="$WORK_DIR/tc2"
SAVED=$(sh "$SCRIPT" "$WORK_DIR/test-b64.txt" "$OUT_DIR" "dark workspace" "gemini" "a dark workspace" 2>/dev/null)
if [ -f "$SAVED" ]; then
pass "TC2 base64 decode: PNG file created"
else
fail "TC2 base64 decode: PNG file created" "file not found: $SAVED"
fi
SIDECAR="${SAVED%.png}.json"
if [ -f "$SIDECAR" ]; then
pass "TC2 base64 decode: JSON sidecar created"
else
fail "TC2 base64 decode: JSON sidecar created" "sidecar not found: $SIDECAR"
fi
# --- Test 3: Naming convention check: YYYYMMDD-HHMMSS_*_gemini_v1.png ---
# GIVEN save-image.sh ran as in TC2
# WHEN we inspect the returned filename
# THEN it matches the expected pattern
FNAME=$(basename "$SAVED")
if printf '%s\n' "$FNAME" | grep -qE '^[0-9]{8}-[0-9]{6}_.+_gemini_v[0-9]+\.png$'; then
pass "TC3 naming convention: $FNAME matches YYYYMMDD-HHMMSS_*_gemini_vN.png"
else
fail "TC3 naming convention" "filename '$FNAME' does not match pattern"
fi
# --- Test 4: Auto-versioning: run twice → v1 and v2 ---
# GIVEN we call save-image.sh twice with identical arguments in the same second
# WHEN we inspect the version suffix
# THEN the first file is v1 and the second is v2
OUT_DIR="$WORK_DIR/tc4"
mkdir -p "$OUT_DIR"
# Force both into the same timestamp by pre-creating the v1 file
TS=$(date +"%Y%m%d-%H%M%S")
PREEXIST="${OUT_DIR}/${TS}_version-test_gemini_v1.png"
touch "$PREEXIST"
SAVED2=$(sh "$SCRIPT" "$WORK_DIR/test-b64.txt" "$OUT_DIR" "version test" "gemini" "version test" 2>/dev/null)
FNAME2=$(basename "$SAVED2")
if printf '%s\n' "$FNAME2" | grep -qE '_v2\.png$'; then
pass "TC4 auto-versioning: second run produces v2"
else
fail "TC4 auto-versioning" "expected v2 suffix, got: $FNAME2"
fi
# --- Test 5: Sidecar JSON has all required fields ---
# GIVEN save-image.sh ran successfully (reuse TC2 output)
# WHEN we read the sidecar JSON
# THEN it contains prompt, provider, model, timestamp, filename
SIDECAR="${SAVED%.png}.json"
JSON=$(cat "$SIDECAR")
check_json_field() {
FIELD="$1"
if printf '%s\n' "$JSON" | grep -q "\"$FIELD\""; then
pass "TC5 sidecar field: $FIELD"
else
fail "TC5 sidecar field: $FIELD" "not found in $SIDECAR"
fi
}
check_json_field "prompt"
check_json_field "provider"
check_json_field "model"
check_json_field "timestamp"
check_json_field "filename"
# --- Test 6: Output dir creation: non-existing dir gets created ---
# GIVEN an output directory that does not exist
# WHEN save-image.sh runs
# THEN the directory is created and the file is saved
NEW_DIR="$WORK_DIR/tc6/nested/new"
SAVED3=$(sh "$SCRIPT" "$WORK_DIR/test-b64.txt" "$NEW_DIR" "newdir test" "gemini" "newdir prompt" 2>/dev/null)
if [ -d "$NEW_DIR" ]; then
pass "TC6 dir creation: output directory created"
else
fail "TC6 dir creation: output directory created" "dir not found: $NEW_DIR"
fi
if [ -f "$SAVED3" ]; then
pass "TC6 dir creation: file saved in new dir"
else
fail "TC6 dir creation: file saved in new dir" "file not found: $SAVED3"
fi
# --- Test 7: Title truncation — long title → max 30 chars in filename stem ---
# GIVEN a very long title (>30 chars)
# WHEN save-image.sh runs
# THEN the title portion of the filename is truncated to 30 characters
LONG_TITLE="this is an extremely long title that should definitely be truncated"
OUT_DIR="$WORK_DIR/tc7"
SAVED4=$(sh "$SCRIPT" "$WORK_DIR/test-b64.txt" "$OUT_DIR" "$LONG_TITLE" "openai" "trunc test" 2>/dev/null)
FNAME4=$(basename "$SAVED4")
# Remove timestamp prefix (YYYYMMDD-HHMMSS_) and suffix (_service_vN.png)
# Remaining is the title portion
TITLE_PART=$(printf '%s\n' "$FNAME4" | sed 's/^[0-9]*-[0-9]*_//' | sed 's/_openai_v[0-9]*\.png$//')
TITLE_LEN=$(printf '%s' "$TITLE_PART" | wc -c | tr -d ' ')
if [ "$TITLE_LEN" -le 30 ]; then
pass "TC7 title truncation: length=$TITLE_LEN (<=30) in '$TITLE_PART'"
else
fail "TC7 title truncation" "title part '$TITLE_PART' has $TITLE_LEN chars, expected <=30"
fi
# --- Cleanup ---
rm -rf "$WORK_DIR"
# --- Summary ---
TOTAL=$((PASS + FAIL))
printf '\n=== RESULTS: %d/%d passed ===\n' "$PASS" "$TOTAL"
if [ "$FAIL" -gt 0 ]; then
printf 'FAILED: %d test(s) failed\n' "$FAIL"
exit 1
fi
exit 0
+11 -19
View File
@@ -24,10 +24,10 @@ from developer to task coordination.
| 6 | agent-creator | opus | Read, Write, Edit | Agent creation and improvement |
| 7 | hook-creator | opus | Read, Write, Edit, Bash | Hook creation and debugging |
| 8 | bash-expert | opus | Read, Write, Edit, Bash | Bash/sh script creation |
| 9 | bc-coordinator | haiku | Read, Write, Edit, Bash | Phase and knowledge coordination |
| 10 | bc-knowledge-manager | haiku | Read, Write | KNOWLEDGE.jsonl compaction |
| 11 | bc-grepai-configurator | opus | Read, Write, Edit, Bash | grepai config.yaml generation |
| 12 | bc-rules-organizer | sonnet | Read, Write, Edit, Bash | .claude/rules/ organization |
| 9 | bc-coordinator | haiku | Read, Write, Edit, Bash | Internal: spawned by /brewcode:start + post-task hook |
| 10 | bc-knowledge-manager | haiku | Read, Write | Internal: spawned by /brewcode:start |
| 11 | bc-grepai-configurator | opus | Read, Write, Edit, Bash | Internal: spawned by /brewcode:grepai |
| 12 | bc-rules-organizer | sonnet | Read, Write, Edit, Bash | Internal: spawned by /brewcode:rules |
<CardGrid>
<Card title="developer" icon="code" href="/brewcode/agents/developer/">
@@ -54,27 +54,19 @@ from developer to task coordination.
<Card title="bash-expert" icon="terminal" href="/brewcode/agents/bash-expert/">
Bash/sh script creation
</Card>
<Card title="bc-coordinator" icon="sync" href="/brewcode/agents/bc-coordinator/">
Phase and knowledge coordination
</Card>
<Card title="bc-knowledge-manager" icon="brain" href="/brewcode/agents/bc-knowledge-manager/">
KNOWLEDGE.jsonl compaction
</Card>
<Card title="bc-grepai-configurator" icon="search" href="/brewcode/agents/bc-grepai-configurator/">
grepai config.yaml generation
</Card>
<Card title="bc-rules-organizer" icon="shield" href="/brewcode/agents/bc-rules-organizer/">
.claude/rules/ organization
</Card>
</CardGrid>
:::note[Internal agents]
`bc-coordinator`, `bc-knowledge-manager`, `bc-grepai-configurator`, and `bc-rules-organizer` are internal. They are spawned automatically by brewcode skills and hooks, are not user-invokable, and have no dedicated page.
:::
## Models and cost
| Model | Agents | When to use |
|-------|--------|-------------|
| **opus** | [developer](/brewcode/agents/developer/), [reviewer](/brewcode/agents/reviewer/), [architect](/brewcode/agents/architect/), [skill-creator](/brewcode/agents/skill-creator/), [agent-creator](/brewcode/agents/agent-creator/), [hook-creator](/brewcode/agents/hook-creator/), [bash-expert](/brewcode/agents/bash-expert/), [bc-grepai-configurator](/brewcode/agents/bc-grepai-configurator/) | Complex tasks, deep analysis, code generation |
| **sonnet** | [tester](/brewcode/agents/tester/), [bc-rules-organizer](/brewcode/agents/bc-rules-organizer/) | Balanced tasks, review, optimization |
| **haiku** | [bc-coordinator](/brewcode/agents/bc-coordinator/), [bc-knowledge-manager](/brewcode/agents/bc-knowledge-manager/) | Lightweight operations: statuses, knowledge extraction, compaction |
| **opus** | [developer](/brewcode/agents/developer/), [reviewer](/brewcode/agents/reviewer/), [architect](/brewcode/agents/architect/), [skill-creator](/brewcode/agents/skill-creator/), [agent-creator](/brewcode/agents/agent-creator/), [hook-creator](/brewcode/agents/hook-creator/), [bash-expert](/brewcode/agents/bash-expert/), bc-grepai-configurator | Complex tasks, deep analysis, code generation |
| **sonnet** | [tester](/brewcode/agents/tester/), bc-rules-organizer | Balanced tasks, review, optimization |
| **haiku** | bc-coordinator, bc-knowledge-manager | Lightweight operations: statuses, knowledge extraction, compaction |
<Callout type="tip" title="Automatic selection">
Agents are selected automatically based on the Phase Registry in PLAN.md.
@@ -1,183 +0,0 @@
---
title: "bc-coordinator"
description: "Brewcode coordinator - extracts knowledge from reports, verifies reports on disk, manages Phase Status table in PLAN.md, generates FINAL.md."
order: 1210
---
import { Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx';
# bc-coordinator
<Callout type="caution">
**The coordinator never writes code.** It validates report files on disk, extracts knowledge entries, updates the Phase Status table in PLAN.md, and generates FINAL.md on completion. Per-phase `Status:` and `Result:` fields are managed exclusively by the manager via the Task API — the coordinator never touches them.
</Callout>
<Callout type="tip">
**Called automatically by `/brewcode:start`.** You never invoke bc-coordinator directly. The manager calls it after each agent completes, passing the report path as a flat text prompt. On task completion, the manager calls it one final time with `mode: finalize`.
</Callout>
## Quick reference
| Field | Value |
|-------|-------|
| Agent | `bc-coordinator` |
| Model | haiku |
| Tools | Read, Write, Edit, Bash |
| Permission mode | acceptEdits |
| Invoked by | `/brewcode:start` manager (never directly) |
| Modes | `initialize`, `standard`, `finalize` |
## When to use
- **Phase just completed** — manager writes `{AGENT}_output.md`, then calls coordinator with `mode: standard` and the report path
- **Task starting** — manager calls coordinator with `mode: initialize` to validate the PLAN.md structure, create the lock file, and transition status from `pending` to `in progress`
- **Task finished or failed** — manager calls coordinator with `mode: finalize` to write FINAL.md and set the terminal status on line 1 of PLAN.md
- **KNOWLEDGE.jsonl nearing capacity** — coordinator auto-compacts when entry count reaches `maxEntries * 0.8`, deduplicating and sorting by priority (`❌` > `✅` > ``)
## Examples
**Initialize at task start:**
```
mode: initialize
taskPath: .claude/tasks/20260417-120000_my-feature_task/PLAN.md
```
Coordinator validates the task structure, creates the `.lock` file, and flips line 1 from `status: pending` to `status: in progress`.
**After an agent completes (standard mode):**
```
mode: standard
taskPath: .claude/tasks/20260417-120000_my-feature_task/PLAN.md
report: artifacts/1-1e/developer_output.md
```
Coordinator verifies the file exists on disk, reads it, extracts 310 KNOWLEDGE entries, and updates the Phase Status table.
**Finalize on success:**
```
mode: finalize
taskPath: .claude/tasks/20260417-120000_my-feature_task/PLAN.md
status: finished
```
Generates FINAL.md from the report template, sets line 1 to `status: finished`. The stop hook reads this value — any non-terminal status blocks session exit.
## Flow
<Steps>
<li>
<div>
<strong>Receive mode + taskPath</strong>
<p>The manager sends a flat text prompt specifying <code>mode</code>, <code>taskPath</code>, and (in standard mode) the <code>report</code> path. Coordinator reads lines 13 of PLAN.md for current state.</p>
</div>
</li>
<li>
<div>
<strong>Verify report on disk</strong>
<p>In <code>standard</code> mode: checks that <code>&#123;AGENT&#125;_output.md</code> exists at the given path. If missing — returns an error immediately. The manager must write the file before calling coordinator.</p>
</div>
</li>
<li>
<div>
<strong>Extract knowledge</strong>
<p>Reads the report and appends 310 genuinely reusable entries to KNOWLEDGE.jsonl using the schema {'`{"ts":"ISO","t":"❌|✅|","txt":"...","src":"agent"}`'}. Skips phase summaries, vague statements, and progress notes.</p>
</div>
</li>
<li>
<div>
<strong>Update Phase Status table</strong>
<p>Adds or updates the row for the current phase in the <code>## Phase Status</code> section at the bottom of PLAN.md. This is the <em>only</em> PLAN.md body section the coordinator ever writes.</p>
</div>
</li>
<li>
<div>
<strong>Auto-compact KNOWLEDGE if needed</strong>
<p>Counts entries. If count is at or above <code>maxEntries \* 0.8</code>: deduplicates by exact <code>txt</code> match, sorts by priority then timestamp descending, trims to <code>maxEntries</code>, and atomically rewrites the file.</p>
</div>
</li>
<li>
<div>
<strong>Return summary</strong>
<p>Prints phase number, report verification result, KNOWLEDGE entry count, compaction status, and an explicit next-action recommendation for the manager.</p>
</div>
</li>
</Steps>
<details>
<summary>Coordinator protocol & artifact rules</summary>
### Modes in detail
**initialize** — called once at `/brewcode:start`:
1. Validates task file exists and has a `## Phase Registry` section
2. Accepts status `pending`, `in progress`, or `handoff` (allows restart after crash)
3. Writes `.lock` file (always overwrites — enables recovery): `{"task_path":"...","started_at":"ISO"}`
4. Sets line 1 to `status: in progress`
5. Validates/updates `.claude/TASK.md` reference (single-line path)
**standard** — called after each agent:
1. Read PLAN.md header (lines 13)
2. Verify report file exists on disk — error if missing
3. Read report, extract 310 KNOWLEDGE entries
4. Update Phase Status table (add row or update existing)
5. Update header lines 23 (`current_phase`, `total_phases`) if phase completed
6. Auto-compact KNOWLEDGE if entry count >= threshold
**finalize** — called on task completion:
1. Generate FINAL.md from `$BC_PLUGIN_ROOT/templates/reports/FINAL.md.template`
2. If `status: failed` — include failure summary from KNOWLEDGE.jsonl
3. Set line 1 to `status: finished` (or `failed`)
4. Lock deletion is handled by the stop hook, not coordinator
### PLAN.md header format (first 3 lines)
```
status: in progress
current_phase: 2
total_phases: 5
```
Terminal statuses for line 1: `finished`, `failed`, `cancelled`, `error`. Any other value blocks session exit via the stop hook.
### Phase Status table
```markdown
## Phase Status
| # | Status | Started | Completed | Iterations |
|---|--------|---------|-----------|------------|
| 1 | completed | 2026-01-26T14:00 | 2026-01-26T14:30 | 1 |
| 1V | completed | 2026-01-26T14:31 | 2026-01-26T14:45 | 1 |
| 2 | in_progress | 2026-01-26T14:46 | - | 1 |
```
If the section does not exist — coordinator creates it at the end of PLAN.md. The `Completed` column is `-` while in progress, ISO timestamp when done.
### Artifact directory layout
```
{TS}_{NAME}_task/artifacts/
├── FINAL.md
└── {P}-{N}{T}/ # e.g., 1-1e/ (phase 1, iter 1, exec)
├── {AGENT}_output.md
└── summary.md
```
### What coordinator never does
- Implement code
- Fabricate or hallucinate report content
- Create `{AGENT}_output.md` — manager writes these before calling coordinator
- Edit per-phase `Status:` or `Result:` fields in PLAN.md body (Task API only)
- Read files from `phases/` directory
</details>
<CardGrid>
<Card title="brewcode overview" icon="document" href="/brewcode/">
All brewcode skills, agents, and hooks in one place.
</Card>
<Card title="/brewcode:start" icon="rocket" href="/brewcode/skills/start/">
The skill that drives task execution and calls bc-coordinator at each phase boundary.
</Card>
<Card title="GitHub source" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewcode/agents/bc-coordinator.md">
Full coordinator protocol and agent definition.
</Card>
</CardGrid>
<UpdateNotice />
@@ -1,171 +0,0 @@
---
title: "bc-grepai-configurator"
description: "grepai config specialist - project analysis, config.yaml generation, verification. Triggers 'configure grepai', 'grepai config', 'analyze for grepai', 'setup grepai index'."
order: 1212
---
import { Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx';
# bc-grepai-configurator
<Callout type="caution">
**grepai without a tuned config wastes cycles and returns noise.** Default chunking is too small for Java/Kotlin, hybrid search is off, and test files compete with production code in results. Parallelism defaults may trigger the [Ollama concurrency bug](https://github.com/ollama/ollama/issues/12591) and stall indexing silently.
</Callout>
<Callout type="tip">
**Trigger the agent with natural language.** Say `"configure grepai"` or `"setup grepai index"` and it handles the rest — infrastructure check, language detection, config generation, MCP wiring, and verification. Assumes grepai and Ollama are already installed.
</Callout>
## Quick reference
| Field | Value |
|-------|-------|
| Model | opus |
| Tools | Read, Write, Edit, Bash, WebFetch, Glob, Grep |
| Permission mode | acceptEdits |
| Triggers | "configure grepai", "grepai config", "analyze for grepai", "setup grepai index" |
| Scope | Config generation only — does not install grepai or Ollama |
## When to use
- **New project** — generate `.grepai/config.yaml` from scratch after cloning or creating a repo
- **Wrong search results** — test files outranking production code, or queries returning unrelated modules
- **Language mismatch** — chunking and trace settings need tuning after adding Java/Kotlin to a JS/TS repo
- **After embedder switch** — switching from `bge-m3` to `mxbai-embed-large` requires a full index reset
- **MCP not wired** — `grepai_search` tool missing from Claude Code after installation
## Examples
```
configure grepai
```
```
setup grepai index for this Spring Boot monorepo
```
```
analyze for grepai — I have embedded SQL in JDBC repositories
```
## Flow
<Steps>
<li>
<div>
<strong>Infrastructure check</strong>
<p>Verifies grepai binary, Ollama daemon, and the <code>bge-m3</code> embedder model. Stops with a clear error if any component is missing — no partial config written.</p>
</div>
</li>
<li>
<div>
<strong>Project analysis</strong>
<p>Runs Glob and Grep in parallel: detects build files (<code>pom.xml</code>, <code>build.gradle</code>, <code>package.json</code>), test directories, generated code paths, and embedded SQL patterns. Produces a structured analysis used in the next phase.</p>
</div>
</li>
<li>
<div>
<strong>Config generation</strong>
<p>Writes <code>.grepai/config.yaml</code> with language-tuned chunking, search boost rules (penalties for tests/generated code, bonuses for core/main), hybrid search for JVM stacks, and trace settings scoped to detected extensions only. Strips <code>watch.last_index_time</code> to avoid the index-skip bug.</p>
</div>
</li>
<li>
<div>
<strong>MCP wiring</strong>
<p>Checks for an existing grepai MCP entry in <code>.mcp.json</code> (project) or <code>&#126;/.claude.json</code> (global). If missing, shows the exact JSON block and the one-liner: <code>claude mcp add grepai -- grepai mcp-serve</code>.</p>
</div>
</li>
<li>
<div>
<strong>Verification</strong>
<p>Confirms config exists, runs a test search, checks index size, and reports MCP status. Prints an indexed summary table — infrastructure, analysis, config settings, and next steps.</p>
</div>
</li>
</Steps>
<details>
<summary>Internals — config.yaml template + phase details</summary>
**Generated config.yaml skeleton:**
```yaml
version: 1
embedder:
provider: ollama
model: bge-m3
endpoint: http://localhost:11434
dimensions: 1024
parallelism: 1 # Always 1 — Ollama concurrency bug #12591
store:
backend: gob
chunking:
size: 512 # 768-1024 for Java/Kotlin
overlap: 50 # 75-100 for Java/Kotlin
watch:
debounce_ms: 500
# last_index_time: NEVER include — causes file-skip bug
search:
boost:
enabled: true
penalties:
# Tests: 0.5, Mocks: 0.4, Generated: 0.4
bonuses:
# Main source: 1.1, Core/domain: 1.2
hybrid:
enabled: false # true for Java/Kotlin
k: 60
trace:
mode: fast
enabled_languages:
# Only extensions detected in Phase 2
exclude_patterns:
# Test file patterns from Phase 2
update:
check_on_startup: false
ignore:
- .git
- .grepai
# Project-specific from .gitignore analysis
```
**Embedded SQL detection (Phase 2):** Grep pattern `JdbcTemplate|NamedParameterJdbcTemplate|@Query|String sql|"""\s*SELECT` → sets `HAS_EMBEDDED_SQL`. When true, adds a warning header to config.yaml and the verify phase runs `grepai trace callers` instead of `trace_graph` to avoid the 2000+ false-edge explosion.
**Chunking by stack:**
| Stack | size | overlap |
|-------|------|---------|
| Java/Kotlin (Spring, JPA) | 7681024 | 75100 |
| TypeScript (React, NestJS) | 512768 | 5075 |
| JavaScript (Node) | 512 | 50 |
| SQL migrations | 384 | 40 |
**Embedder options:**
| Model | Dims | RAM | Best for |
|-------|------|-----|----------|
| `bge-m3` (default) | 1024 | 1.5 GB | Multilingual |
| `mxbai-embed-large` | 1024 | 1 GB | English, max accuracy |
| `nomic-embed-text` | 768 | 500 MB | Fast, small repos |
</details>
<CardGrid>
<Card title="grepai skill" icon="search" href="/brewcode/skills/grepai/">
The `/brewcode:grepai` skill that orchestrates setup — calls this agent as part of its flow.
</Card>
<Card title="GitHub source" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewcode/agents/bc-grepai-configurator.md">
Agent definition, phase instructions, and config reference.
</Card>
<Card title="Brewcode overview" icon="document" href="/brewcode/">
Full brewcode plugin — skills, agents, and the infinite task execution loop.
</Card>
</CardGrid>
<UpdateNotice />
@@ -1,150 +0,0 @@
---
title: "bc-knowledge-manager"
description: "Compacts KNOWLEDGE.jsonl: deduplicates entries, merges similar, enforces priority order. Spawned before handoff or when the coordinator reports duplicates."
order: 1211
---
import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx';
# bc-knowledge-manager
<Callout type="caution">
**KNOWLEDGE.jsonl grows with every task.** Duplicate entries, similar patterns across different wordings, and low-priority noise accumulate quickly — the file bloats, compaction at handoff slows, and the most important ❌ entries get buried. The `pre-compact.mjs` hook fires before every auto-compact, but it can't help if the file is already in poor shape.
</Callout>
<Callout type="tip">
**bc-knowledge-manager runs automatically.** The `bc-coordinator` spawns it before handoff and whenever duplicates are reported. You can also trigger it manually via Task tool with an explicit `knowledgePath` and `mode`. It never loses ❌ entries unless they are exact duplicates.
</Callout>
## Quick reference
| Field | Value |
|-------|-------|
| Model | haiku |
| Tools | Read, Write |
| Permission mode | acceptEdits |
| Spawned by | bc-coordinator (via Task tool) |
| Triggers | Before handoff, when duplicates reported by coordinator |
## When to use
- **Before a session handoff** — compact KNOWLEDGE.jsonl so the next session starts with a clean, prioritized file
- **After `/brewcode:rules` export** — run `prune-rules` mode to strip ❌/✅ entries that have been promoted to rules files
- **When coordinator reports duplicates** — deduplicate-only pass with `mode: dedupe` to keep the file clean mid-task
- **When the file exceeds 100 entries** — full compaction removes excess, prioritizing ❌ over ✅ over
## Examples
```jsonl
# KNOWLEDGE.jsonl entry format
{"ts":"2026-04-17T10:00:00Z","t":"❌","txt":"Avoid SELECT * in queries — causes N+1 on large tables","src":"developer"}
{"ts":"2026-04-17T10:01:00Z","t":"✅","txt":"Use Read then Write (not Edit) for full file rewrites","src":"bc-coordinator"}
{"ts":"2026-04-17T10:02:00Z","t":"","txt":"Project uses PostgreSQL 15 with pgvector extension","src":"architect"}
```
```
# Spawn via Task tool (full compaction)
Task: bc-knowledge-manager
Prompt: knowledgePath=/abs/path/.claude/tasks/20260417_example_task/KNOWLEDGE.jsonl mode=full maxEntries=100
# Output
Knowledge compaction complete:
- Before: 134 entries
- After: 87 entries
- Removed: 12 duplicates, 21 merged, 14 truncated
- By type: ❌ 31, ✅ 28, 28
- Size: 18420 bytes
```
```
# Prune after rules export (prune-rules mode)
Task: bc-knowledge-manager
Prompt: knowledgePath=/abs/path/KNOWLEDGE.jsonl mode=prune-rules
# Output
Pruned 59 entries (❌/✅), kept 28 entries ()
```
## Flow
<Steps>
<li>
<div>
<strong>Read</strong>
<p>Reads KNOWLEDGE.jsonl at <code>knowledgePath</code>. File not found or empty — reports and exits without writing.</p>
</div>
</li>
<li>
<div>
<strong>Parse</strong>
<p>Parses every line as JSON. Malformed lines are skipped and counted separately — they do not halt processing.</p>
</div>
</li>
<li>
<div>
<strong>Deduplicate & merge</strong>
<p>Removes entries with identical <code>txt</code>. Then merges entries whose <code>txt</code> matches case-insensitively on the first 100 characters — keeps the higher-priority type (❌ wins over ✅ wins over ).</p>
</div>
</li>
<li>
<div>
<strong>Sort & truncate</strong>
<p>Sorts by priority (❌ → ✅ → ), then by timestamp descending. If the entry count exceeds <code>maxEntries</code> (default 100), lowest-priority and oldest entries are dropped first. ❌ entries are never removed unless they were exact duplicates.</p>
</div>
</li>
<li>
<div>
<strong>Write</strong>
<p>Rewrites the file using Read then Write (never Edit). One valid JSON object per line, original timestamps preserved.</p>
</div>
</li>
<li>
<div>
<strong>Report</strong>
<p>Returns a statistics block: before/after counts, removed breakdown (duplicates / merged / truncated), by-type counts, and final file size in bytes.</p>
</div>
</li>
</Steps>
<details>
<summary>Priority &amp; dedup rules</summary>
**Entry types (priority order)**
| Type | Priority | Meaning |
|------|----------|---------|
| `❌` | 1 — highest | Avoid: mistakes, failures, known anti-patterns |
| `✅` | 2 | Best practice: what works reliably |
| `` | 3 — lowest | Info: neutral facts, architecture notes |
**Dedup matching**
Exact match on `txt` field → remove the lower-priority copy (or older if same priority).
Similar match on first 100 characters of `txt` (case-insensitive) → merge into one entry, keep higher-priority `t` value and newer `ts`.
**Merge mode: `prune-rules`**
After `/brewcode:rules` exports ❌/✅ entries to `.claude/rules/` files, run `prune-rules` to strip them from KNOWLEDGE.jsonl. Only `` entries survive. This prevents double-loading the same knowledge as both KNOWLEDGE and rules.
**Rules frontmatter note**
When rules are exported via `/brewcode:rules`, use `paths` (array of glob strings) in frontmatter — `globs` and `alwaysApply` are not supported. Rules without `paths` load always; path-specific rules should load lazily (Bug #16299 causes all to load at session start regardless).
</details>
<CardGrid>
<Card title="bc-coordinator" icon="robot" href="/brewcode/agents/bc-coordinator/">
Spawns bc-knowledge-manager before handoff and after duplicate reports.
</Card>
<Card title="brewcode:start" icon="rocket" href="/brewcode/skills/start/">
Infinite execution skill — triggers compaction via pre-compact.mjs hook at context limit.
</Card>
<Card title="GitHub source" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewcode/agents/bc-knowledge-manager.md">
Agent definition and compaction logic.
</Card>
<Card title="Brewcode overview" icon="document" href="/brewcode/">
All brewcode skills, agents, and hooks in one place.
</Card>
</CardGrid>
<UpdateNotice />
@@ -1,185 +0,0 @@
---
title: "bc-rules-organizer"
description: "Creates and optimizes .claude/rules/*.md files with path-specific frontmatter. Triggered by 'organize rules', 'path-specific rules', 'extract rules', 'split CLAUDE.md'."
order: 1213
---
import { Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx';
# bc-rules-organizer
<Callout type="caution">
**One giant CLAUDE.md loaded for every file is expensive.** Rules for React components load even when Claude is editing SQL migrations. Claude Code supports `paths:` frontmatter in `.claude/rules/*.md` to scope rules to file patterns — but setting it up correctly requires knowing the right fields, quoting conventions, and dedup logic. Bug [#16299](https://github.com/anthropics/claude-code/issues/16299): all rules still load at session start regardless of `paths:`, so keep files lean.
</Callout>
<Callout type="tip">
**Invoke `bc-rules-organizer` to extract, split, and optimize rules files.** The agent reads any source (CLAUDE.md, docs, code comments), distributes rules by path pattern, runs the 3-Check Dedup Protocol, and finishes with `brewtools:text-optimize` on every created file. See the [rules skill](/brewcode/skills/rules/) for KNOWLEDGE-to-rules conversion.
</Callout>
## Quick reference
| Field | Value |
|-------|-------|
| Model | sonnet |
| Tools | Read, Write, Edit, Glob, Grep, Bash, Skill |
| Skills used | `brewtools:text-optimize` |
| Permission mode | `acceptEdits` |
| Triggers | "organize rules", "path-specific rules", "extract rules", "split CLAUDE.md" |
## When to use
- **Split a bloated CLAUDE.md** — extract sections into path-scoped rule files and replace with `@path/to/rule.md` references
- **Scope rules to file types** — React rules only for `src/components/**/*.tsx`, SQL rules only for `**/*Repository*`
- **Deduplicate across files** — merge semantically similar entries, eliminate cross-file antonym pairs
- **Refactor existing rules** — add missing `paths:` frontmatter, fix unquoted globs, enforce table format standards
- **Consolidate code comments** — extract actionable rules scattered in source files into `.claude/rules/`
## Examples
```bash
# Extract rules from CLAUDE.md and distribute by path pattern
"organize rules from CLAUDE.md"
"extract rules from CLAUDE.md"
```
```bash
# Create path-specific rules for a module
"path-specific rules for src/components"
"create rules file for bq-core module"
```
```bash
# Refactor and deduplicate existing rules
"split CLAUDE.md into rule files"
"optimize .claude/rules/ — merge duplicates, add paths frontmatter"
```
## Flow
<Steps>
<li>
<div>
<strong>Analysis — ask at most 2 questions</strong>
<p>Identifies the source file (CLAUDE.md, docs, code) and any explicit path patterns. If not provided, auto-detects from project structure. Reads existing <code>.claude/rules/</code> files to map what's already covered.</p>
</div>
</li>
<li>
<div>
<strong>Extraction — group by scope</strong>
<p>Classifies every rule as anti-pattern (avoid) or best practice. Groups rules into logical scopes: component rules, API rules, test rules, build config, module-level. Each group maps to a target file and a <code>paths:</code> pattern.</p>
</div>
</li>
<li>
<div>
<strong>3-Check Dedup Protocol</strong>
<p>Before writing any entry: (1) within-file similarity — skip if &gt;70% overlap, merge if 4070%; (2) cross-file antonym — "don't do X" in avoid + "do not-X" in best-practice = keep avoid entry only; (3) CLAUDE.md duplicate — concept already in CLAUDE.md → skip entirely. Source column value "CLAUDE.md" is forbidden.</p>
</div>
</li>
<li>
<div>
<strong>File creation — standard structure</strong>
<p>Creates <code>avoid.md</code> / <code>best-practice.md</code> for global rules (no <code>paths:</code>) and <code>&#123;'&#123;prefix&#125;'&#125;-avoid.md</code> / domain files with quoted glob patterns. Max 20 rows per table — splits into specialized files if exceeded. All entries numbered sequentially.</p>
</div>
</li>
<li>
<div>
<strong>Optimization — brewtools:text-optimize on every file</strong>
<p>Applies token-efficiency transforms: tables over prose, abbreviations, lazy documentation links (<code>&gt; Details: [file.md](path)</code>) instead of inline content, remove filler. Final files are dense and LLM-efficient.</p>
</div>
</li>
</Steps>
<details>
<summary>Frontmatter reference, file naming, and output report</summary>
**Supported fields:** only `paths:` — `globs`, `alwaysApply`, `description` are not valid Claude Code fields.
```yaml
---
paths:
- "src/components/**/*.tsx"
- "src/components/**/*.ts"
- "!src/components/**/*.test.tsx"
---
```
Quoting rules — patterns must be quoted strings, array format required, brace expansion needs quotes: `"{src,lib}/**"`.
**File naming:**
| Convention | Examples | Use for |
|------------|----------|---------|
| `avoid.md`, `best-practice.md` | Global, no `paths:` | Pure anti-pattern or practice collections |
| `{prefix}-avoid.md`, `{prefix}-best-practice.md` | `test-avoid.md`, `sql-best-practice.md` | Path-scoped by tech or type |
| Descriptive domain file | `react-components.md`, `bq-core.md` | Mixed rules for a specific module/stack |
Common prefixes: `test`, `sql`, `api`, `security`, `performance`, `kotlin`, `java`, `react`.
**Table formats (authoritative):**
Avoid table: `| # | Avoid | Instead | Why |`
Best practice table: `| # | Practice | Context | Source |`
Both require sequential `#` column, max 20 rows, "CLAUDE.md" forbidden as Source value.
**Pattern examples:**
| Pattern | Matches |
|---------|---------|
| `"**/*.kt"` | All Kotlin files |
| `"src/main/**/*.java"` | Java in src/main |
| `"bq-core/**/*"` | All files in bq-core |
| `"!**/*.test.ts"` | Exclude test files |
| `"*.md"` | Root markdown files only |
**Example transformation:**
Input CLAUDE.md prose section → Output `.claude/rules/react-components.md`:
```markdown
---
paths:
- "src/components/**/*.tsx"
- "src/components/**/*.ts"
---
# React Component Rules
| # | Avoid | Instead | Why |
|---|-------|---------|-----|
| 1 | `export default` | `export function Name()` | Explicit imports, easier tracking |
| 2 | Inline styles | Separate `*.styles.ts` | Separation of concerns |
```
**Output report format — always returned as final response:**
```markdown
## Rules Organization Complete
### Created/Updated Files
| File | Paths | Change |
|------|-------|--------|
| `react-components.md` | `src/components/**/*` | New |
| `test-avoid.md` | `**/*.test.*` | Updated |
### Stats
| Metric | Value |
|--------|-------|
| Files created | 2 |
| Files updated | 1 |
| Total rules | 18 |
```
</details>
<CardGrid>
<Card title="Rules skill" icon="document" href="/brewcode/skills/rules/">
Convert KNOWLEDGE.jsonl entries into structured rules files — complementary to bc-rules-organizer.
</Card>
<Card title="GitHub source" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewcode/agents/bc-rules-organizer.md">
Agent definition, capabilities, and workflow phases.
</Card>
<Card title="Brewcode overview" icon="rocket" href="/brewcode/">
All brewcode agents, skills, and hooks in one place.
</Card>
</CardGrid>
<UpdateNotice />
@@ -178,9 +178,6 @@ A **post-session lifecycle hook** runs after a session ends and before the works
<Card title="GitHub source" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewcode/agents/hook-creator.md">
Agent definition with full routing matrix, templates, and validation checklist.
</Card>
<Card title="BC Coordinator" icon="wrench" href="/brewcode/agents/bc-coordinator/">
The task coordination agent — uses hooks for phase gating and knowledge injection.
</Card>
</CardGrid>
<UpdateNotice />
+1 -1
View File
@@ -218,7 +218,7 @@ Handles the Task tool result: binds the session and reminds about the 2-step pro
| Timeout | 5000 ms |
**Logic:**
- If [bc-coordinator](/brewcode/agents/bc-coordinator/) finished -- binds session_id to the lock file
- If bc-coordinator finished -- binds session_id to the lock file
- If a worker agent finished ([developer](/brewcode/agents/developer/), [tester](/brewcode/agents/tester/), etc.) -- reminds: "WRITE report -> CALL bc-coordinator"
- System agents -- skipped
@@ -201,7 +201,7 @@ After running [`/brewcode:setup`](/brewcode/skills/setup/) and [`/brewcode:start
| Review | reviewer | opus |
| Creation | skill-creator, agent-creator, hook-creator | opus |
| Optimization | bash-expert | opus |
| Coordination | bc-coordinator, bc-knowledge-manager, bc-grepai-configurator, bc-rules-organizer | haiku/sonnet/opus |
| Coordination (internal) | bc-coordinator, bc-knowledge-manager, bc-grepai-configurator, bc-rules-organizer | haiku/sonnet/opus |
+ dynamic project agents created by [`/brewcode:teams`](/brewcode/skills/teams/)
</TabItem>
@@ -72,7 +72,7 @@ Stops watch, wipes the index, rebuilds from scratch, restarts watch. Monitor wit
<li><div><strong>Mode detection</strong><p>The skill runs <code>detect-mode.sh</code> against <code>$ARGUMENTS</code>. Keywords like <code>setup</code>, <code>start</code>, <code>status</code> map to modes; empty args auto-detect from whether <code>.grepai/</code> exists; unrecognized text falls back to interactive prompt.</p></div></li>
<li><div><strong>Infra check (setup/optimize)</strong><p>Verifies Homebrew, Ollama daemon, bge-m3 model download, and grepai CLI. Stops with a clear error if any component is missing.</p></div></li>
<li><div><strong>MCP configuration</strong><p>Configures the grepai MCP server entry in <code>.claude/settings.json</code> and adds <code>mcp__grepai__\*</code> to <code>allowedTools</code>. Required once per project.</p></div></li>
<li><div><strong>Config generation — bc-grepai-configurator agent</strong><p>The <a href="/brewcode/agents/bc-grepai-configurator/">bc-grepai-configurator</a> agent (opus) analyzes build files, source layout, and test patterns to produce an optimal <code>.grepai/config.yaml</code> with boost weights and trace-language settings.</p></div></li>
<li><div><strong>Config generation — bc-grepai-configurator agent</strong><p>The bc-grepai-configurator agent (opus) analyzes build files, source layout, and test patterns to produce an optimal <code>.grepai/config.yaml</code> with boost weights and trace-language settings.</p></div></li>
<li><div><strong>Index build</strong><p>Runs <code>init-index.sh</code> synchronously. Embeds all source files via bge-m3 and writes GOB shards to <code>.grepai/</code>. Large repos (5k+ files) take 1030 min — monitor the log.</p></div></li>
<li><div><strong>Rule creation</strong><p>Writes a <code>.claude/rules/grepai-first.md</code> rule so Claude always reaches for <code>grepai_search</code> / <code>trace_callers</code> / <code>trace_callees</code> before Glob or Grep.</p></div></li>
<li><div><strong>Verification</strong><p>Runs <code>verify.sh</code> — confirms MCP responds, index is readable, and the rule file exists. Prints a status table with ✅/❌ per component.</p></div></li>
@@ -133,9 +133,6 @@ The skill always prints a status table after any mode completes:
</details>
<CardGrid>
<Card title="bc-grepai-configurator" icon="robot" href="/brewcode/agents/bc-grepai-configurator/">
The opus agent that analyzes your project and generates the optimal <code>.grepai/config.yaml</code>.
</Card>
<Card title="setup skill" icon="document" href="/brewcode/skills/setup/">
Run setup first — it installs all prerequisites including Ollama and grepai CLI.
</Card>
@@ -43,7 +43,7 @@ bash "${CLAUDE_SKILL_DIR}/scripts/rules.sh" list
## File / Prompt / Session Mode
Spawn [bc-rules-organizer](/brewcode/agents/bc-rules-organizer/) agent via Task tool.
Spawn bc-rules-organizer agent via Task tool.
### Prepare Knowledge by Mode
@@ -164,9 +164,6 @@ Escalation after repeated agent failures:
<Card title="Plan" icon="document" href="/brewcode/skills/plan/">
Creates the PLAN.md that start executes. Run plan before start.
</Card>
<Card title="bc-coordinator" icon="robot" href="/brewcode/agents/bc-coordinator/">
Called after every agent to validate reports and update task state.
</Card>
<Card title="GitHub source" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewcode/skills/start">
Source SKILL.md, phase templates, and execution logic.
</Card>
@@ -150,7 +150,7 @@ Execution Loop: TaskList() -> pending+unblocked -> spawn agents
```
1. **Resolve path** -- from arguments or `.claude/TASK.md`
2. **Initialize** -- [bc-coordinator](/brewcode/agents/bc-coordinator/) creates the lock, sets status to `in progress`
2. **Initialize** -- bc-coordinator creates the lock, sets status to `in progress`
3. **Load context** -- reads PLAN.md and KNOWLEDGE.jsonl (NOT phases/ -- those are for agents)
4. **Create tasks** -- TaskCreate for each Phase Registry row
5. **Set dependencies** -- TaskUpdate with addBlockedBy
@@ -359,10 +359,10 @@ System agents (Explore, Plan, general-purpose) do not receive the `## K` block.
After all phases are complete:
1. **[bc-coordinator](/brewcode/agents/bc-coordinator/)** generates `FINAL.md` with consolidated results
1. **bc-coordinator** generates `FINAL.md` with consolidated results
2. Task status -> `finished`
3. [`/brewcode:rules`](/brewcode/skills/rules/) extracts knowledge into `.claude/rules/`
4. [`bc-knowledge-manager`](/brewcode/agents/bc-knowledge-manager/) removes synced entries from KNOWLEDGE.jsonl
4. `bc-knowledge-manager` removes synced entries from KNOWLEDGE.jsonl
5. Lock file is deleted on the next Stop
<Callout type="tip" title="After completion">
@@ -89,7 +89,7 @@ brewdoc/
│ ├── publish/ # brewpage.app publishing
│ └── guide/ # Interactive tutorial
└── agents/
└── bd-auto-sync-processor # File processing agent
└── bd-auto-sync-processor # Internal: spawned by /brewdoc:auto-sync
```
The single hook `pre-task.mjs` injects the `BD_PLUGIN_ROOT` variable into subagent prompts
@@ -12,7 +12,7 @@ import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../..
</Callout>
<Callout type="tip">
**One command syncs everything in scope.** Auto-Sync discovers markdown files, checks what's stale via an INDEX, and delegates parallel updates to `bd-auto-sync-processor` agents. Run `status` first to see what's out of date before touching anything.
**One command syncs everything in scope.** Auto-Sync discovers markdown files, checks what's stale via an INDEX, and delegates parallel updates to internal `bd-auto-sync-processor` agents. Run `status` first to see what's out of date before touching anything.
</Callout>
## Quick reference
@@ -19,14 +19,14 @@ import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../..
| Command | Action |
|---------|--------|
| `/brewtools:skill-toggle disable brewui:image-gen` | Hide a skill (renames `SKILL.md` → `_SKILL.md`) |
| `/brewtools:skill-toggle enable brewui:image-gen` | Restore a hidden skill |
| `/brewtools:skill-toggle disable brewdoc:md-to-pdf` | Hide a skill (renames `SKILL.md` → `_SKILL.md`) |
| `/brewtools:skill-toggle enable brewdoc:md-to-pdf` | Restore a hidden skill |
| `/brewtools:skill-toggle status` | Show all disabled skills (merged global + project) |
| `/brewtools:skill-toggle list` | List every installed skill with enabled/disabled state |
| `/brewtools:skill-toggle reapply` | Re-apply state after manual plugin cache changes |
| `/brewtools:skill-toggle prune` | Remove state entries for uninstalled plugins |
Target format: `plugin:name` — e.g., `brewui:image-gen`, `brewcode:convention`. Name without a plugin prefix triggers a clarifying question before any mutation.
Target format: `plugin:name` — e.g., `brewdoc:md-to-pdf`, `brewcode:convention`. Name without a plugin prefix triggers a clarifying question before any mutation.
## When to use
@@ -39,11 +39,11 @@ Target format: `plugin:name` — e.g., `brewui:image-gen`, `brewcode:convention`
```bash
# Disable a skill globally (default scope)
/brewtools:skill-toggle disable brewui:image-gen
/brewtools:skill-toggle disable brewdoc:md-to-pdf
# Natural language also works
"disable brewui:image-gen"
"hide the image-gen skill"
"disable brewdoc:md-to-pdf"
"hide the md-to-pdf skill"
```
```bash
@@ -51,7 +51,7 @@ Target format: `plugin:name` — e.g., `brewui:image-gen`, `brewcode:convention`
/brewtools:skill-toggle disable brewcode:convention --scope=project
# Enable a previously disabled skill
/brewtools:skill-toggle enable brewui:image-gen
/brewtools:skill-toggle enable brewdoc:md-to-pdf
```
```bash
@@ -103,7 +103,7 @@ Four phases:
</Steps>
<Callout type="note">
**Explicit commands skip the flow.** `disable brewui:image-gen` runs directly — no questions asked. The interactive path only triggers when your intent is ambiguous.
**Explicit commands skip the flow.** `disable brewdoc:md-to-pdf` runs directly — no questions asked. The interactive path only triggers when your intent is ambiguous.
</Callout>
## How it works
@@ -155,10 +155,10 @@ Project scope overrides global per key — a project-level enable wins over a gl
```json
{
"disabled": {
"brewui:image-gen": {
"brewdoc:md-to-pdf": {
"kind": "skill",
"plugin": "brewui",
"name": "image-gen",
"plugin": "brewdoc",
"name": "md-to-pdf",
"disabled_at": "2026-04-16T10:30:00.000Z",
"last_applied_version": "3.5.2"
}
+4 -4
View File
@@ -1,6 +1,6 @@
---
title: "Agents"
description: "All Brewui agents: models, triggers, tools"
description: "Brewui agents: none (plugin is an empty placeholder)"
order: 37
---
@@ -8,14 +8,14 @@ import { Card, CardGrid } from '../../../components/mdx';
# Agents
Brewui currently ships no dedicated agents. Its functionality is delivered entirely
through the `image-gen` skill.
Brewui currently ships no dedicated agents. The plugin is an empty placeholder for
future UI/visual/creative tools.
<CardGrid>
<Card title="Latest Release" icon="rocket" href="https://github.com/kochetkov-ma/claude-brewcode/releases/latest">
Download, changelog, and installation instructions.
</Card>
<Card title="View on GitHub" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewui/agents">
<Card title="View on GitHub" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewui">
Source code, README, and configuration files.
</Card>
</CardGrid>
+13 -27
View File
@@ -1,6 +1,6 @@
---
title: "Brewui Overview"
description: "UI/visual/creative tools plugin for Claude Code: AI image generation via multiple providers"
description: "UI/visual/creative tools plugin for Claude Code: placeholder, currently empty but installable"
order: 35
---
@@ -8,9 +8,9 @@ import { Card, CardGrid, Callout, InstallPrompt } from '../../../components/mdx'
# Brewui Overview
Brewui is a plugin for UI/visual/creative tools: AI image generation via multiple providers
with anti-AI-slop controls. Each skill is self-contained
and requires no prior setup beyond an API key.
Brewui is a placeholder plugin for future UI/visual/creative tools. It currently ships
no skills or agents, but it is fully installable and registers its hooks, so it can be
wired into your suite ahead of time. Content will be added in a future release.
## Installation
@@ -20,27 +20,19 @@ Install the entire suite:
<InstallPrompt plugin="all" mode="install" />
## Skills (recipes)
<Callout type="note" title="Currently empty">
Brewui installs cleanly and registers its hooks, but ships no skills or agents yet.
Installing it now is safe; tools will appear here in a future release.
</Callout>
<CardGrid>
<Card title="image-gen" icon="sparkle" href="/brewui/skills/image-gen/">
AI image generation via 4 providers: Gemini Imagen 4, OpenRouter Gemini 2.5 Flash,
OpenRouter GPT-5, OpenAI DALL-E 3. Anti-slop prompt engineering.
Four modes: generate, edit, config, update.
</Card>
</CardGrid>
## Skills
## Commands
| Command | Purpose | Model | Arguments |
|---------|---------|-------|-----------|
| [`/brewui:image-gen`](/brewui/skills/image-gen/) | AI image generation | haiku | `[prompt] [--edit] [--config] [--update] [--service] [--style]` |
No skills yet -- coming soon.
## Plugin variable
`BU_PLUGIN_ROOT` -- injected by the SessionStart hook into every session context.
Skills in the main conversation use `${CLAUDE_SKILL_DIR}` to access their own files;
subagents use `$BU_PLUGIN_ROOT` to locate plugin resources.
Subagents use `$BU_PLUGIN_ROOT` to locate plugin resources once skills are added.
## Architecture
@@ -53,17 +45,11 @@ brewui/
│ ├── session-start.mjs # BU_PLUGIN_ROOT injection
│ ├── pre-task.mjs # BU_PLUGIN_ROOT into subagents
│ └── lib/utils.mjs # I/O utilities
└── skills/
└── image-gen/ # AI image generation
├── SKILL.md
├── references/ # Provider specs, anti-slop, modes
├── scripts/ # API request, parsing, saving
└── tests/ # Integration tests
└── skills/ # Empty -- placeholder for future tools
```
<Callout type="note" title="Brewui vs Brewcode">
**Brewui** provides standalone visual/creative tools: image generation.
Each skill works independently with no lifecycle dependencies.
**Brewui** is reserved for standalone visual/creative tools. It is currently empty.
**Brewcode** is a task execution engine with infinite context, lifecycle hooks,
KNOWLEDGE.jsonl, and session handoff.
+7 -19
View File
@@ -1,6 +1,6 @@
---
title: "Skills"
description: "All Brewui skills: commands, parameters, examples"
description: "Brewui skills: none yet, coming soon"
order: 36
---
@@ -8,31 +8,19 @@ import { Card, CardGrid, Callout } from '../../../components/mdx';
# Skills
Skills (recipes) are slash commands that define *what* to do. Brewui includes 1 skill
focused on visual and creative tools -- it works independently with no prior setup beyond an API key.
Brewui currently ships **no skills**. This plugin is a placeholder for future
UI/visual/creative tools and installs cleanly so it can be added to your suite ahead of time.
## Summary table
| # | Skill | Command | Model | Purpose |
|---|-------|---------|-------|---------|
| 1 | [image-gen](/brewui/skills/image-gen/) | [`/brewui:image-gen`](/brewui/skills/image-gen/) | haiku | AI image generation via multiple providers |
<CardGrid>
<Card title="image-gen" icon="sparkle" href="/brewui/skills/image-gen/">
AI image generation via multiple providers with anti-slop controls
</Card>
</CardGrid>
<Callout type="tip" title="Standalone">
The skill can be used independently -- it requires no prior setup
and no dependency on Brewcode or Brewdoc plugins. An API key for the chosen provider is required.
<Callout type="note" title="No skills yet -- coming soon">
Skills will appear here in a future release. Installing Brewui now is safe; it registers
its hooks and reserves the `/brewui:*` command namespace without adding any commands yet.
</Callout>
<CardGrid>
<Card title="Latest Release" icon="rocket" href="https://github.com/kochetkov-ma/claude-brewcode/releases/latest">
Download, changelog, and installation instructions.
</Card>
<Card title="View on GitHub" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewui/skills">
<Card title="View on GitHub" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewui">
Source code, README, and configuration files.
</Card>
</CardGrid>
@@ -1,153 +0,0 @@
---
title: "image-gen"
description: "AI image generation via multiple providers with anti-AI-slop prompt engineering. Modes: generate, edit, config, update."
order: 3501
---
import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx';
# image-gen — anti-slop image gen
<Callout type="caution">
**Raw prompts produce AI-looking images.** Symmetrical faces, plastic skin, impossible reflections, airbrushed gradients — the usual tells. The skill applies a style-matched anti-slop prefix automatically so you don't have to fight defaults every time.
</Callout>
<Callout type="tip">
**Fast path: just type a prompt.** No flags needed — the skill picks Gemini Imagen 4, photo style, 1024×1024, and goes. Only asks questions when something is genuinely missing (API key, or you passed `--count`/`--style` flags explicitly).
</Callout>
## Quick reference
| Field | Value |
|-------|-------|
| Command | `/brewui:image-gen` |
| Arguments | `[prompt] [--edit image.png 'instructions'] [--config] [--update] [--service] [--style] [--count N] [--output dir] [--size WxH]` |
| Model | haiku |
| Tools | Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, WebSearch |
| Output | PNG files + sidecar JSON metadata in `.claude/reports/images/` |
## When to use
- **Quick OG image** — `"minimalist tech blog header, dark mode, purple accents"` and done
- **Batch variations** — `--count 4` to compare options before committing to one
- **Edit an existing image** — `--edit hero.png "remove background, add soft shadow"` (Gemini + OpenAI only)
- **Cost-conscious iteration** — use OpenRouter Gemini 2.5 Flash (~$0.001) for drafts, switch to Imagen 4 for finals
- **API key setup** — `--config` walks through key entry, validation, and storage once
## Examples
```bash
# Default: Gemini Imagen 4, photo style, 1024×1024
/brewui:image-gen "developer at a standing desk, morning light through large windows"
```
```bash
# Illustration style, custom provider
/brewui:image-gen --style illustration --service openrouter "tech blog header, geometric shapes, dark background"
```
```bash
# Edit an existing image (Gemini or OpenAI only)
/brewui:image-gen --edit ./hero.png "remove the background, increase contrast"
```
## Providers
| Provider | Model | Speed | Quality | Cost |
|----------|-------|-------|---------|------|
| `gemini` (default) | Imagen 4 | Fast | Very High | Paid plan required |
| `openrouter` | Gemini 2.5 Flash Image | Fast | High | ~$0.001/image |
| `openrouter-gpt5` | GPT-5 Image | Medium | Highest | ~$0.01/image |
| `openai` | DALL-E 3 | Medium | High | $0.040.12/image |
Edit support: `gemini` (native), `openai` (DALL-E 2 fallback). OpenRouter redirects to a supported provider.
## Flow
<Steps>
<li>
<div>
<strong>Parse arguments</strong>
<p>Runs <code>parse-args.sh</code> to extract flags. Detects mode from explicit flags first, then natural language signals ("edit this", "configure key"), then defaults to <strong>generate</strong>.</p>
</div>
</li>
<li>
<div>
<strong>Resolve API key</strong>
<p>Checks in order: inline in prompt text → <code>.env</code> → shell environment variable → interactive config (Phase C). Stops here if no key is found and guides setup.</p>
</div>
</li>
<li>
<div>
<strong>Fast-path or gather params</strong>
<p>Prompt provided, no extra flags? Skip count/service/style/output questions — use defaults straight away. Explicit flags or missing prompt triggers targeted questions only.</p>
</div>
</li>
<li>
<div>
<strong>Build enhanced prompt</strong>
<p>Loads the anti-slop prefix for the chosen style from <code>references/anti-slop.md</code>, prepends it to your prompt, then constructs the provider JSON payload.</p>
</div>
</li>
<li>
<div>
<strong>Send request &amp; save</strong>
<p>Calls the provider API, parses base64 or URL response, saves each image as <code>kebab-title-NNN.png</code> with a sidecar <code>.json</code> (prompt, service, style, size, timestamp, cost estimate).</p>
</div>
</li>
<li>
<div>
<strong>Report &amp; offer next action</strong>
<p>Prints a results table with file paths, provider, cost estimate. Asks: generate more, different prompt, edit one, or done.</p>
</div>
</li>
</Steps>
<details>
<summary>Full provider matrix, anti-slop rules, and parameter reference</summary>
### Anti-slop prefixes by style
| Style | Enforces | Bans |
|-------|----------|------|
| `photo` | Real lighting physics, correct anatomy, natural material textures, depth of field | Plastic skin, impossible reflections, symmetrical faces |
| `illustration` | Clean line work, proper color theory, organic imperfections, consistent style | Airbrushed gradients, floating elements, generic clip-art feel |
| `art` | Unified brushwork, intentional composition, coherent color temperature, visible technique | Mixed-media confusion, over-processed look |
### All parameters
| Parameter | Default | Options | Description |
|-----------|---------|---------|-------------|
| `--service` | gemini | gemini, openrouter, openrouter-gpt5, openai | Provider |
| `--style` | photo | photo, illustration, art | Anti-slop preset |
| `--count` | 1 | 110 | Images per generation (DALL-E 3: sequential requests) |
| `--size` | 1024x1024 | WxH | Image dimensions |
| `--output` | `.claude/reports/images/` | Directory path | Save location |
| `--edit` | — | `<image.png> 'instructions'` | Edit mode |
| `--config` | — | — | API key setup |
| `--update` | — | — | Check providers for latest models/pricing |
### API key priority
1. Explicit key pasted in prompt text
2. `.env` in project root (`source .env`)
3. Shell environment variable
4. Interactive config (Phase C)
For team projects use `.env` (add to `.gitignore`). For personal use `&#126;/.zshrc` works well.
### Update mode
Runs WebSearch for each provider's latest models and pricing, compares against `references/providers.md`, and offers to update the file if changes are detected.
</details>
<CardGrid>
<Card title="GitHub source" icon="link" href="https://github.com/kochetkov-ma/claude-brewcode/tree/main/brewui/skills/image-gen">
Source code, anti-slop references, and provider specs.
</Card>
<Card title="Brewui overview" icon="document" href="/brewui/">
All brewui skills in one place.
</Card>
</CardGrid>
<UpdateNotice />
+1 -1
View File
@@ -71,7 +71,7 @@ Paste the following prompt directly into the chat. The coercive phrasing is inte
| **brewcode** | Infinite task execution, 13 skills, 12 agents, 9 hooks | `claude plugin install brewcode@claude-brewcode` |
| **brewdoc** | Documentation tools: sync, memory, PDF, publishing | `claude plugin install brewdoc@claude-brewcode` |
| **brewtools** | Text utilities, [SSH](/brewtools/skills/ssh/), [deploy](/brewtools/skills/deploy/), [debate](/brewtools/skills/debate/), [plugin-update](/brewtools/skills/plugin-update/) | `claude plugin install brewtools@claude-brewcode` |
| **brewui** | AI image generation | `claude plugin install brewui@claude-brewcode` |
| **brewui** | UI/visual/creative tools (placeholder, empty) | `claude plugin install brewui@claude-brewcode` |
All four plugins install from the same `claude-brewcode` marketplace on GitHub.
@@ -24,7 +24,7 @@ import { Card, CardGrid, Callout, InstallPrompt, Spoiler } from '../../component
Universal utilities: prompt optimization, AI artifact removal, secrets scanning, SSH, deploy, evidence-based debates. 13 skills · 3 agents.
</Card>
<Card title="brewui" icon="image" href="/brewui/overview/">
UI / visual / creative: AI image generation with anti-slop controls. 1 skill · 0 agents.
UI / visual / creative tools (placeholder, currently empty). 0 skills · 0 agents.
</Card>
<Card title="brewdoc" icon="file" href="/brewdoc/overview/">
Documentation tools: auto-sync from official sources, memory optimization, Markdown → PDF, interactive guide. 6 skills · 1 agent.
@@ -47,7 +47,7 @@ import { Card, CardGrid, Callout, InstallPrompt, Spoiler } from '../../component
Knowledge is injected into every agent prompt and converted into project rules.
</Card>
<Card title="Skills and agents" icon="settings" href="/brewcode/skills/">
33 skills and 16 specialized agents across 4 plugins. Built-in tools for
32 skills and 16 specialized agents across 4 plugins. Built-in tools for
creating your own skills, agents, and hooks. Prompt optimization included.
</Card>
</CardGrid>
@@ -58,7 +58,7 @@ import { Card, CardGrid, Callout, InstallPrompt, Spoiler } from '../../component
|--------|---------|--------|--------|-------|
| **brewcode** | Infinite tasks, codebase exploration, review, prompt optimization, skill/agent creation | 13 | 12 | 9 |
| **brewtools** | Text utilities: prompt optimization, AI artifact removal, secrets scanning, SSH, deploy | 13 | 3 | — |
| **brewui** | UI / visual / creative: AI image generation | 1 | 0 | — |
| **brewui** | UI / visual / creative tools (placeholder, empty) | 0 | 0 | — |
| **brewdoc** | Documentation tools: sync, generation, memory optimization, PDF conversion | 6 | 1 | — |
All four plugins install with a single marketplace and load automatically with every Claude Code session.
+1 -1
View File
@@ -147,7 +147,7 @@ claude plugin update brewui@claude-brewcode
Run your first infinite task in 15 minutes: [setup](/brewcode/skills/setup/), [spec](/brewcode/skills/spec/), [plan](/brewcode/skills/plan/), [start](/brewcode/skills/start/).
</Card>
<Card title="Brewcode Overview" icon="building" href="/brewcode/overview/">
Architecture, concepts, all 33 skills, 16 agents, and 9 hooks.
Architecture, concepts, all 32 skills, 16 agents, and 9 hooks.
</Card>
</CardGrid>
+1 -1
View File
@@ -105,7 +105,7 @@ By the end you will have a specification, a plan, and a running task with automa
secrets scanning, SSH, deploy.
</Card>
<Card title="brewui" icon="image" href="/brewui/overview/">
1 skill for UI/visual/creative tools: AI image generation.
Placeholder for future UI/visual/creative tools (currently empty).
</Card>
<Card title="brewdoc" icon="document" href="/brewdoc/overview/">
6 skills for documentation: automatic sync with the codebase,
+2 -11
View File
@@ -55,10 +55,6 @@ export const navigation: NavSection[] = [
{ title: 'agent-creator', slug: 'brewcode/agents/agent-creator' },
{ title: 'hook-creator', slug: 'brewcode/agents/hook-creator' },
{ title: 'bash-expert', slug: 'brewcode/agents/bash-expert' },
{ title: 'bc-coordinator', slug: 'brewcode/agents/bc-coordinator' },
{ title: 'bc-knowledge-manager', slug: 'brewcode/agents/bc-knowledge-manager' },
{ title: 'bc-grepai-configurator', slug: 'brewcode/agents/bc-grepai-configurator' },
{ title: 'bc-rules-organizer', slug: 'brewcode/agents/bc-rules-organizer' },
],
},
{ title: 'Hooks', slug: 'brewcode/hooks' },
@@ -104,13 +100,8 @@ export const navigation: NavSection[] = [
title: 'Brewui',
items: [
{ title: 'Overview', slug: 'brewui/overview' },
{
title: 'Skills',
slug: 'brewui/skills',
children: [
{ title: 'image-gen', slug: 'brewui/skills/image-gen' },
],
},
{ title: 'Skills', slug: 'brewui/skills' },
{ title: 'Agents', slug: 'brewui/agents' },
],
},
{