<instructions GLM Design-to-Code Converts design inputs (screenshots, text descriptions, HTML files, URLs) to working frontend code using GLM vision models. Three modes: CREATE, REVIEW, FIX. Arguments: Mode Routing | Mode | Flow | |------|------| | CREATE | Phase 0 → 0.5 → 1 → 2 → 3 (with auto-fix) → 4 (mandatory verify) → 5 (if --review) | | REVIEW | Phase 0 → 0.5 → 1 → 5 | | FIX | Phase 0 → 0.5 → 1 → 6 | PARAMETER PRIORITY: User prompt arguments ALWAYS override defaults and environment. 1. Explicit flags in ( , , , ) → highest priority 2. API keys from prompt text (if user pasted a key inli…

.gitignore 2>/dev/null || echo '.env' >> .gitignore\necho \"KEY_SAVED to .env ($VAR)\"\n```\n\n### Step 5: Choose Where to Save Key Permanently\n\n**ASK** using AskUserQuestion:\n```\nAPI key validated. Where should it be saved permanently?\n\n- CLAUDE.local.md — Claude Code local config (not committed, Claude reads at startup)\n- ~/.zshrc — system-wide, available in all terminals and projects\n- .env — project-local dotenv file (gitignored, sourced by skill)\n```\nOptions:\n- \"Save to CLAUDE.local.md (Claude Code standard, recommended)\"\n- \"Save to ~/.zshrc (system-wide)\"\n- \"Keep in .env only (already saved)\"\n\n**On \"CLAUDE.local.md\":**\n\n`CLAUDE.local.md` is a standard Claude Code file in the project root — local instructions read by Claude at session start, not committed to git.\n\n**EXECUTE** using Bash tool:\n```bash\n. .env\nPROVIDER=\"PROVIDER_HERE\"\nif [ \"$PROVIDER\" = \"zai\" ]; then\n VAR=\"ZAI_API_KEY\"\n VAL=\"$ZAI_API_KEY\"\nelse\n VAR=\"OPENROUTER_API_KEY\"\n VAL=\"$OPENROUTER_API_KEY\"\nfi\nif [ -f CLAUDE.local.md ]; then\n grep -q \"$VAR\" CLAUDE.local.md && echo \"Already in CLAUDE.local.md\" || printf '\\n## GLM API Key\\n\\nBefore running glm-design-to-code, set env var:\\n`export %s=%s`\\n' \"$VAR\" \"$VAL\" >> CLAUDE.local.md\nelse\n printf '# Local Config\\n\\n## GLM API Key\\n\\nBefore running glm-design-to-code, set env var:\\n`export %s=%s`\\n' \"$VAR\" \"$VAL\" > CLAUDE.local.md\nfi\necho \"Saved to CLAUDE.local.md\"\n```\n\n**On \"~/.zshrc\":**\n\n**EXECUTE** using Bash tool:\n```bash\n. .env\nPROVIDER=\"PROVIDER_HERE\"\nif [ \"$PROVIDER\" = \"zai\" ]; then\n echo \"export ZAI_API_KEY=\\\"$ZAI_API_KEY\\\"\" >> ~/.zshrc\nelse\n echo \"export OPENROUTER_API_KEY=\\\"$OPENROUTER_API_KEY\\\"\" >> ~/.zshrc\nfi\necho \"Saved to ~/.zshrc (available in new terminal sessions)\"\n```\n\n**On \".env only\":** Already saved in Step 3. Done, continue to Phase 1.\n\n---\n\n## Phase 1: Validate Prerequisites\n\n### Step 1: Check Tools and API Keys\n\n**EXECUTE** using Bash tool:\n```bash\n[ -f .env ] && . .env\nPROVIDER=\"PROVIDER_HERE\"\necho \"=== Tools ===\"\ncommand -v jq && echo \"jq OK\" || echo \"jq MISSING\"\ncommand -v curl && echo \"curl OK\" || echo \"curl MISSING\"\ncommand -v base64 && echo \"base64 OK\" || echo \"base64 MISSING\"\necho \"=== API Key ===\"\nif [ \"$PROVIDER\" = \"zai\" ]; then\n [ -n \"$ZAI_API_KEY\" ] && echo \"ZAI_API_KEY SET\" || echo \"ZAI_API_KEY MISSING\"\nelif [ \"$PROVIDER\" = \"openrouter\" ]; then\n [ -n \"$OPENROUTER_API_KEY\" ] && echo \"OPENROUTER_API_KEY SET\" || echo \"OPENROUTER_API_KEY MISSING\"\nfi\necho \"=== Framework Tools ===\"\ncommand -v node && echo \"node $(node -v)\" || echo \"node MISSING\"\ncommand -v npx && echo \"npx OK\" || echo \"npx MISSING\"\ncommand -v flutter && echo \"flutter OK\" || echo \"flutter MISSING (only needed for flutter framework)\"\n```\n\n> **STOP if jq, curl, or API key MISSING** -- tell user what to install/set.\n\n### Step 2: Resolve Scripts Path\n\nAll pipeline scripts are at `${CLAUDE_SKILL_DIR}/scripts/`. Verify they exist:\n\n**EXECUTE** using Bash tool:\n```bash\nSD=\"${CLAUDE_SKILL_DIR}/scripts\"\nfor s in glm-build-request.sh glm-build-text-request.sh glm-request.sh glm-extract.sh glm-verify.sh; do\n [ -f \"$SD/$s\" ] && echo \"$s OK\" || echo \"$s MISSING\"\ndone\n```\n\n> **STOP if any MISSING** -- re-install plugin.\n\n---\n\n## Phase 2: Build and Send Request\n\n### Step 1: Select Prompt and Context Files\n\n| Framework | Prompt | Context |\n|-----------|--------|---------|\n| html | `references/profile-{PROFILE}.md` | (none) |\n| react | `references/profile-{PROFILE}.md` | `references/context-react.md` |\n| flutter | `references/profile-{PROFILE}.md` | `references/context-flutter.md` |\n| custom | `references/profile-{PROFILE}.md` | User-provided or `references/context-template.md` |\n\nRead the prompt file to confirm it exists:\n\n**EXECUTE** using Bash tool:\n```bash\nPROMPT=\"${CLAUDE_SKILL_DIR}/references/profile-PROFILE_HERE.md\"\n[ -f \"$PROMPT\" ] && echo \"PROMPT OK: $PROMPT\" || echo \"PROMPT MISSING\"\n```\n\nFor custom framework: **ASK** user to describe their stack. Write to `/tmp/d2c-custom-context.md` using `context-template.md` as template.\n\n### Step 2: Resolve Model ID\n\n**If MODEL was set via `--model`:** Use it directly, but ensure OpenRouter prefix:\n- If PROVIDER=openrouter and MODEL does not start with `z-ai/` → prepend `z-ai/` (e.g., `glm-4.6v` → `z-ai/glm-4.6v`)\n- If PROVIDER=zai and MODEL starts with `z-ai/` → strip the prefix (e.g., `z-ai/glm-5v-turbo` → `glm-5v-turbo`)\n\n**If MODEL is empty (no `--model` flag):** Use defaults:\n\n| Provider | Default Model ID |\n|----------|-----------------|\n| zai | `glm-5v-turbo` |\n| openrouter | `z-ai/glm-5v-turbo` |\n\n### Step 2.5: Display Resolved Configuration\n\n> **MANDATORY** — output before ANY API call in ALL modes. Shows user exactly what was resolved from their prompt, flags, env, and defaults. Mark overridden values with source.\n\n```markdown\n## Resolved Configuration\n\n| Setting | Value | Source |\n|---------|-------|--------|\n| Mode | `{MODE}` | {auto-detected / --review / --fix} |\n| Input | `{IMAGE}` ({INPUT_TYPE}) | {argument / prompt text} |\n| Framework | `{FRAMEWORK}` | {--framework / default: html} |\n| Profile | `{PROFILE}` (max_tokens={MAX_TOKENS}) | {--profile / default: max} |\n| Provider | `{PROVIDER}` | {--provider / default: zai} |\n| Model | `{MODEL}` | {--model / default for provider} |\n| Intent | `{INTENT}` | {auto-detected from prompt / default: reproduce} |\n| Instruction | `{first 80 chars of GLM_INSTRUCTION}...` | {formulated from intent + user prompt} |\n| Dual Input | `{yes/no}` | {HTML screenshotted / image only / text only} |\n| API Key | `{VAR_NAME}=***{last 4 chars}` | {prompt / .env / shell env} |\n| Output | `{OUTPUT}` | {--output / default: ./d2c-output} |\n\n**Expected result:** {description based on mode — e.g., \"HTML/CSS files in ./d2c-output\" or \"Review score with differences\" or \"Targeted fixes to existing code\"}\n```\n\n### Step 3: Build Request Payload\n\nRoute to the correct script based on input type, dual input flag, and intent:\n\n| INPUT_TYPE | DUAL_INPUT | Script | Extra args |\n|------------|-----------|--------|------------|\n| image | N/A | `glm-build-request.sh` | `\"$GLM_INSTRUCTION\"` |\n| html | true | `glm-build-request.sh` | `\"$GLM_INSTRUCTION\" \"$HTML_FILE\"` |\n| html | false | `glm-build-text-request.sh` | `\"$GLM_INSTRUCTION\"` |\n| text | N/A | `glm-build-text-request.sh` | `\"$GLM_INSTRUCTION\"` |\n| url | N/A | `glm-build-request.sh` | `\"$GLM_INSTRUCTION\"` |\n\n**For INPUT_TYPE=image or url (or html with DUAL_INPUT=true):**\n\n**EXECUTE** using Bash tool:\n```bash\nSD=\"${CLAUDE_SKILL_DIR}/scripts\"\nPROMPT=\"${CLAUDE_SKILL_DIR}/references/profile-PROFILE_HERE.md\"\nCONTEXT=\"CONTEXT_PATH_OR_EMPTY\"\nIMAGE=\"IMAGE_PATH_HERE\"\nMODEL=\"MODEL_ID_HERE\"\nGLM_INSTRUCTION=\"INSTRUCTION_HERE\"\nHTML_SOURCE=\"HTML_FILE_OR_EMPTY\"\n\nbash \"$SD/glm-build-request.sh\" \"$IMAGE\" \"$PROMPT\" \"$CONTEXT\" \"$MODEL\" MAX_TOKENS_HERE 0.2 0.85 \"$GLM_INSTRUCTION\" \"$HTML_SOURCE\" > /tmp/d2c-payload.json && echo \"PAYLOAD OK ($(wc -c \u003c /tmp/d2c-payload.json | tr -d ' ') bytes)\" || echo \"PAYLOAD FAILED\"\n```\n\nReplace all placeholders with actual values. For non-dual HTML or non-HTML input, leave HTML_SOURCE empty (\"\").\n\n**For INPUT_TYPE=html (DUAL_INPUT=false) or INPUT_TYPE=text:**\n\n**EXECUTE** using Bash tool:\n```bash\nSD=\"${CLAUDE_SKILL_DIR}/scripts\"\nPROMPT=\"${CLAUDE_SKILL_DIR}/references/profile-PROFILE_HERE.md\"\nCONTEXT=\"CONTEXT_PATH_OR_EMPTY\"\nINPUT=\"INPUT_VALUE_HERE\"\nMODEL=\"MODEL_ID_HERE\"\nGLM_INSTRUCTION=\"INSTRUCTION_HERE\"\n\nbash \"$SD/glm-build-text-request.sh\" \"$INPUT\" \"$PROMPT\" \"$CONTEXT\" \"$MODEL\" MAX_TOKENS_HERE 0.2 0.85 \"$GLM_INSTRUCTION\" > /tmp/d2c-payload.json && echo \"PAYLOAD OK ($(wc -c \u003c /tmp/d2c-payload.json | tr -d ' ') bytes)\" || echo \"PAYLOAD FAILED\"\n```\n\n> For text input, INPUT is the description string. For HTML input, INPUT is the file path.\n> Note: text-only requests can use non-vision models (glm-4.7-flash, glm-5-turbo) which may be cheaper.\n\n> **STOP if FAILED** -- check image path, prompt file.\n\n### Step 4: Send to API\n\n**EXECUTE** using Bash tool:\n```bash\n[ -f .env ] && . .env\nSD=\"${CLAUDE_SKILL_DIR}/scripts\"\nbash \"$SD/glm-request.sh\" /tmp/d2c-payload.json /tmp/d2c-response.json PROVIDER_HERE && echo \"API OK\" || echo \"API FAILED\"\n```\n\n> **STOP if FAILED** -- check API key, network, provider.\n\n**Check for truncation:**\n```bash\nFINISH=$(jq -r '.choices[0].finish_reason' /tmp/d2c-response.json)\n[ \"$FINISH\" = \"stop\" ] && echo \"COMPLETE\" || echo \"WARNING: finish_reason=$FINISH (may be truncated)\"\n```\n\n---\n\n## Phase 3: Extract and Build\n\n### Step 1: Extract and Validate Files\n\n**EXECUTE** using Bash tool:\n```bash\nSD=\"${CLAUDE_SKILL_DIR}/scripts\"\nOUTPUT=\"OUTPUT_DIR_HERE\"\nmkdir -p \"$OUTPUT\"\nbash \"$SD/glm-extract.sh\" /tmp/d2c-response.json \"$OUTPUT\"\nEXIT_CODE=$?\necho \"EXIT_CODE=$EXIT_CODE\"\n[ $EXIT_CODE -eq 0 ] && echo \"EXTRACT OK\" || [ $EXIT_CODE -eq 1 ] && echo \"EXTRACT PARTIAL\" || echo \"EXTRACT FAILED\"\n```\n\n**Handle exit codes:**\n- `0` (OK) → continue to Step 2\n- `1` (partial) → Claude Code reads `/tmp/d2c-response.json` raw content using Read tool and manually extracts missing files using Write tool. Look for code blocks, `===FILE:` markers, or inline code that the script missed\n- `2` (fail) → Claude Code reads `/tmp/d2c-response.json` and extracts ALL files manually\n\n**Validate key files exist** (framework-dependent):\n\n| Framework | Required file(s) |\n|-----------|------------------|\n| React | `src/main.jsx` or `src/App.jsx` + `package.json` |\n| Flutter | `lib/main.dart` + `pubspec.yaml` |\n| HTML | `index.html` |\n\nIf required files are missing → read `/tmp/d2c-response.json` with Read tool, find the code, write files with Write tool.\n\n> **STOP only if response.json contains no usable code at all.**\n\n### Step 2: List Extracted Files\n\n**EXECUTE** using Bash tool:\n```bash\nOUTPUT=\"OUTPUT_DIR_HERE\"\necho \"=== Extracted Files ===\"\nfind \"$OUTPUT\" -type f | head -50 | while read -r f; do\n echo \" $(echo \"$f\" | sed \"s|$OUTPUT/||\") ($(wc -l \u003c \"$f\" | tr -d ' ') lines)\"\ndone\necho \"=== Total ===\"\nfind \"$OUTPUT\" -type f | wc -l | tr -d ' '\n```\n\n### Step 3: Build and Auto-Fix\n\n#### Step 3a: Build\n\nClaude Code determines the framework from extracted files and builds the project:\n- Analyze file structure (package.json → Node/React, pubspec.yaml → Flutter, index.html without bundler deps → static HTML)\n- Install dependencies if needed\n- Run the appropriate build tool\n- Create any missing config files required for build\n\n> Do NOT hardcode specific build commands — Claude Code knows how to build any stack. Analyze the actual project files and choose the right approach.\n\nBuild log → `/tmp/d2c-build-log.txt`. If build succeeds → go to Phase 4. If build fails → Step 3b.\n\n**HTML framework:** No build step needed — skip directly to Phase 4.\n\n#### Step 3b: Auto-Fix (max 3 attempts)\n\n> **Claude Code fixes build errors directly — NO external API calls, NO GLM requests.**\n\nClaude Code reads the build output, diagnoses compilation/build errors, and applies MINIMAL fixes.\n\n**RULES:**\n- ONLY fix compilation/build errors\n- Do NOT change design, colors, layout, fonts, spacing\n- Do NOT refactor or rename anything\n- Do NOT add functionality\n- Each fix = smallest possible change\n\n**Typical patterns** (hints, NOT exhaustive — Claude Code diagnoses from actual errors):\n- Missing import/dependency → add it\n- Syntax error → fix syntax\n- Unresolved reference → create stub or fix name\n- Incompatible API → replace with compatible equivalent\n- Missing config/entry file → create minimal version\n\nAfter applying fixes: increment ATTEMPT counter. If ATTEMPT ≤ 3 → go back to Step 3a. If ATTEMPT > 3 → STOP, report full error log to user.\n\n#### Step 3c: Report Build Result\n\n```markdown\n## Build Result\n\n| Metric | Value |\n|--------|-------|\n| Build attempts | {N} |\n| Fixes applied | {list of fixes} |\n| Final status | OK / FAILED |\n```\n\n> **If FAILED after 3 attempts:** Include full last build error log so user can diagnose manually.\n\n---\n\n## Phase 4: Verify (Mandatory for CREATE mode)\n\n> **Required** for CREATE mode. Skip only if Playwright is completely unavailable.\n\n### Step 1: Serve and Screenshot\n\n**EXECUTE** using Bash tool:\n```bash\nSD=\"${CLAUDE_SKILL_DIR}/scripts\"\nOUTPUT=\"OUTPUT_DIR_HERE\"\nbash \"$SD/glm-verify.sh\" \"$OUTPUT\" 8900\n```\n\nThis outputs a URL. Take a screenshot with framework-appropriate timeout:\n\n| Framework | Timeout | Reason |\n|-----------|---------|--------|\n| HTML | (none) | Static content, loads instantly |\n| React | `--wait-for-timeout=3000` | Vite dev server + React hydration |\n| Flutter | `--wait-for-timeout=8000` | Flutter web engine initialization |\n\n**EXECUTE** using Bash tool:\n```bash\nFRAMEWORK=\"FRAMEWORK_HERE\"\nTIMEOUT_FLAG=\"\"\n[ \"$FRAMEWORK\" = \"react\" ] && TIMEOUT_FLAG=\"--wait-for-timeout=3000\"\n[ \"$FRAMEWORK\" = \"flutter\" ] && TIMEOUT_FLAG=\"--wait-for-timeout=8000\"\nnpx playwright screenshot --full-page $TIMEOUT_FLAG http://localhost:8900/ /tmp/d2c-result-screenshot.png 2>&1 && echo \"SCREENSHOT OK\" || echo \"SCREENSHOT FAILED\"\n```\n\n> **If SCREENSHOT FAILED:** Double the timeout and retry once:\n```bash\nFRAMEWORK=\"FRAMEWORK_HERE\"\nTIMEOUT_FLAG=\"\"\n[ \"$FRAMEWORK\" = \"react\" ] && TIMEOUT_FLAG=\"--wait-for-timeout=6000\"\n[ \"$FRAMEWORK\" = \"flutter\" ] && TIMEOUT_FLAG=\"--wait-for-timeout=16000\"\n[ \"$FRAMEWORK\" = \"html\" ] && TIMEOUT_FLAG=\"--wait-for-timeout=3000\"\nnpx playwright screenshot --full-page $TIMEOUT_FLAG http://localhost:8900/ /tmp/d2c-result-screenshot.png 2>&1 && echo \"SCREENSHOT OK\" || echo \"SCREENSHOT FAILED\"\n```\n> If still failed → skip screenshot, report URL for manual check.\n\n### Step 2: Validate Screenshot Content\n\nRead the screenshot using Read tool and verify it is not a blank/white page.\n\n**If blank page detected:**\nReport to user: \"Build succeeded but page renders blank — possible runtime error. Check browser console at http://localhost:8900/\"\n\n### Step 3: Cleanup Server\n\n```bash\nbash \"${CLAUDE_SKILL_DIR}/scripts/glm-verify.sh\" --kill && echo \"SERVER STOPPED\"\n```\n\n---\n\n## Phase 5: Review (if --review flag or user requests)\n\nSend both original design and generated screenshot to GLM for automated comparison.\n\n> **ALWAYS** output before sending:\n> ```\n> ## Review Configuration\n> | Setting | Value |\n> |---------|-------|\n> | Original | `{IMAGE}` |\n> | Result | `{RESULT_IMAGE or /tmp/d2c-result-screenshot.png}` |\n> | Provider | `{PROVIDER}` |\n> | Model | `{MODEL}` |\n> ```\n\n### Step 1: Build Review Request\n\nThe review requires sending TWO images. Build a custom payload:\n\n**EXECUTE** using Bash tool:\n```bash\nSD=\"${CLAUDE_SKILL_DIR}/scripts\"\nREVIEW_PROMPT=\"${CLAUDE_SKILL_DIR}/references/review.md\"\nORIGINAL=\"IMAGE_PATH_HERE\"\nRESULT=\"${RESULT_IMAGE:-/tmp/d2c-result-screenshot.png}\"\nMODEL=\"MODEL_ID_HERE\"\n\n[ -f \"$ORIGINAL\" ] && [ -f \"$RESULT\" ] && [ -f \"$REVIEW_PROMPT\" ] && echo \"REVIEW INPUTS OK\" || echo \"REVIEW INPUTS MISSING\"\n```\n\nBuild review payload manually (two images in user message):\n\n```bash\nREVIEW_PROMPT=\"${CLAUDE_SKILL_DIR}/references/review.md\"\nORIGINAL=\"IMAGE_PATH_HERE\"\nRESULT=\"${RESULT_IMAGE:-/tmp/d2c-result-screenshot.png}\"\nMODEL=\"MODEL_ID_HERE\"\n\nSYSTEM=$(cat \"$REVIEW_PROMPT\")\n\n# Base64 encode both images\nif base64 --help 2>&1 | grep -q '\\-w'; then\n B64_ORIG=$(base64 -w0 \"$ORIGINAL\")\n B64_RESULT=$(base64 -w0 \"$RESULT\")\nelse\n B64_ORIG=$(base64 -i \"$ORIGINAL\" | tr -d '\\n')\n B64_RESULT=$(base64 -i \"$RESULT\" | tr -d '\\n')\nfi\n\n# Detect MIME types\ncase \"$ORIGINAL\" in *.png) M1=\"image/png\";; *.jpg|*.jpeg) M1=\"image/jpeg\";; *) M1=\"image/png\";; esac\nM2=\"image/png\"\n\njq -n \\\n --arg model \"$MODEL\" \\\n --arg system \"$SYSTEM\" \\\n --arg uri1 \"data:${M1};base64,${B64_ORIG}\" \\\n --arg uri2 \"data:${M2};base64,${B64_RESULT}\" \\\n '{\n model: $model,\n temperature: 0.2,\n top_p: 0.85,\n max_tokens: 4096,\n messages: [\n { role: \"system\", content: $system },\n { role: \"user\", content: [\n { type: \"text\", text: \"Image 1 (original design):\" },\n { type: \"image_url\", image_url: { url: $uri1 } },\n { type: \"text\", text: \"Image 2 (generated code screenshot):\" },\n { type: \"image_url\", image_url: { url: $uri2 } }\n ]}\n ]\n }' > /tmp/d2c-review-payload.json && echo \"REVIEW PAYLOAD OK\" || echo \"REVIEW PAYLOAD FAILED\"\n```\n\n### Step 2: Send Review\n\n```bash\n[ -f .env ] && . .env\nSD=\"${CLAUDE_SKILL_DIR}/scripts\"\nbash \"$SD/glm-request.sh\" /tmp/d2c-review-payload.json /tmp/d2c-review-response.json PROVIDER_HERE && echo \"REVIEW OK\" || echo \"REVIEW FAILED\"\n```\n\n### Step 3: Extract Review\n\n```bash\nREVIEW=$(jq -r '.choices[0].message.content' /tmp/d2c-review-response.json)\necho \"$REVIEW\"\n```\n\nParse score from `score: N/10` line in the review output.\n\n---\n\n## Phase 6: Fix Mode (if MODE=FIX)\n\n> Skip Phases 2-5. Go directly here if MODE=FIX.\n\n> **ALWAYS** output before fixing:\n> ```\n> ## Fix Configuration\n> | Setting | Value |\n> |---------|-------|\n> | Mode | FIX |\n> | Feedback source | {--fix \"text\" / --review-file path / previous review} |\n> | Target directory | `{OUTPUT}` |\n> | Expected result | Targeted edits to existing code files |\n> ```\n\n### Step 1: Gather Fix Context\n\nRead fix feedback from:\n- `--fix \"text\"` argument → use text directly\n- `--fix --review-file path` → read review JSON from file\n- No explicit feedback → look for `/tmp/d2c-review-response.json` from previous review\n\n**EXECUTE** using Bash tool:\n```bash\n# Check for previous review\n[ -f \"/tmp/d2c-review-response.json\" ] && echo \"PREV_REVIEW EXISTS\" || echo \"NO_PREV_REVIEW\"\n```\n\nIf no feedback source found:\n\n**ASK** using AskUserQuestion:\n```\nNo review feedback found. What needs to be fixed in the generated code?\n\nDescribe specific issues, for example:\n- \"Sidebar is 240px, should be 280px\"\n- \"Header background is #2d2d2d, should be #1a1a2e\"\n- \"Missing syntax highlighting in code blocks\"\n- \"Footer section is completely missing\"\n```\nOptions:\n- \"Describe issues\" (free text)\n- \"Run automated review first\" (switches to REVIEW mode -> Phase 5)\n\n**On \"Describe issues\":** User provides free text feedback -> store as FIX_TEXT, continue to Step 2.\n**On \"Run automated review first\":** Execute Phase 5 (Review), then return to Phase 6 with review feedback.\n\n### Step 2: Read Existing Code\n\n**EXECUTE** using Bash tool:\n```bash\nOUTPUT=\"OUTPUT_DIR_HERE\"\necho \"=== Current Files ===\"\nfind \"$OUTPUT\" -type f -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.jsx' -o -name '*.dart' | head -20 | while read -r f; do\n echo \"--- $f ($(wc -l \u003c \"$f\" | tr -d ' ') lines) ---\"\ndone\n```\n\nRead each file using the Read tool.\n\n### Step 3: Apply Fixes\n\nBased on feedback, use the Edit tool to make targeted changes to the generated code files.\n\nCommon fixes:\n- Color corrections → update CSS custom properties\n- Spacing/sizing → update CSS values\n- Layout issues → restructure HTML/CSS\n- Missing elements → add to relevant files\n\n### Step 4: Re-verify (if Playwright available)\n\nFollow Phase 4 steps to serve, screenshot, and compare.\n\n### Step 5: Report Changes\n\n```markdown\n## Fix Applied\n\n| File | Changes |\n|------|---------|\n| `{file}` | `{description}` |\n\n## Verification\n- Screenshot: `{path or N/A}`\n- Previous score: `{N}/10`\n```\n\n---\n\n## Error Handling\n\n| Condition | Action |\n|-----------|--------|\n| Image not found | AskUserQuestion for correct path |\n| API key missing | \"Set `ZAI_API_KEY` or `OPENROUTER_API_KEY` env var.\" STOP |\n| API returns error | Show error, suggest retry or switch provider |\n| Response truncated | Warn user, suggest `efficient` profile for smaller output |\n| Build fails | Auto-fix loop: Claude Code reads build errors, applies minimal compilation-only fixes (imports, syntax, references, config), retries build (max 3 attempts). Reports all fixes applied. If 3 attempts fail → show full error log to user |\n| Playwright not available | Skip screenshot, report URL for manual check |\n\n---\n\n## Technical Notes\n\n- **Model:** `glm-5v-turbo` (Z.ai) / `z-ai/glm-5v-turbo` (OpenRouter)\n- **Context window:** 202K tokens\n- **Thinking mode:** NOT supported on glm-5v-turbo -- never send thinking parameters\n- **System message split:** Prompt (profile) goes to system role, context + image go to user role\n- **API params:** `temperature: 0.2`, `top_p: 0.85`, `max_tokens: MAX_TOKENS` (profile-dependent: 32768/16384/8192)\n- **File markers:** `===FILE: path===` ... `===END_FILE===`\n\n---\n\n## Output Format\n\n```markdown\n# GLM Design-to-Code\n\n## Configuration\n\n| Setting | Value |\n|---------|-------|\n| Screenshot | `{IMAGE}` |\n| Framework | `{FRAMEWORK}` |\n| Profile | `{PROFILE}` |\n| Provider | `{PROVIDER}` |\n| Model | `{MODEL_ID}` |\n| Output | `{OUTPUT}` |\n\n## API Response\n\n| Metric | Value |\n|--------|-------|\n| Finish reason | `{stop/length}` |\n| Input tokens | `{N}` |\n| Output tokens | `{N}` |\n\n## Extracted Files\n\n| File | Lines |\n|------|-------|\n| `{path}` | `{N}` |\n\n## Build\n\n| Step | Status |\n|------|--------|\n| Install | {OK/FAILED/N/A} |\n| Build | {OK/FAILED/N/A} |\n\n## Review (if requested)\n\n| Metric | Value |\n|--------|-------|\n| Score | `{N}/10` |\n| Summary | `{one-line}` |\n\n### Differences\n- {list}\n\n### Suggestions\n- {list}\n\n## Next Steps\n- {recommendations}\n```\n\n\u003c/instructions>\n---","attachment_filenames":["README.md","references/context-flutter.md","references/context-react.md","references/context-template.md","references/profile-efficient.md","references/profile-max.md","references/profile-optimal.md","references/review.md","scripts/glm-build-request.sh","scripts/glm-build-text-request.sh","scripts/glm-extract.sh","scripts/glm-request.sh","scripts/glm-verify.sh","scripts/parse-args.sh"],"attachments":[{"filename":"README.md","content":"---\nauto-sync: enabled\nauto-sync-date: 2026-04-03\nauto-sync-type: doc\n---\n\n# GLM Design-to-Code\n\nConverts designs to working frontend code using GLM-5V-Turbo vision model. Accepts 4 input types: **image**, **text description**, **HTML file**, or **URL**. Three modes: **CREATE** (generate code), **REVIEW** (evaluate quality), **FIX** (iterate based on feedback). Supports HTML/CSS, React 18, Flutter, or custom frameworks. Powered by Z.ai GLM-5V-Turbo (94.8 Design2Code benchmark) or OpenRouter routing.\n\n## Input Types\n\n| Type | Example | Description |\n|------|---------|-------------|\n| Image | `screenshot.png` | PNG/JPG/WebP/GIF screenshot or design mockup |\n| Text | `\"Dark landing page with hero section\"` | Natural language description of the desired UI |\n| HTML | `existing-page.html` | Convert or improve existing HTML code |\n| URL | `https://example.com` | Takes a Playwright screenshot first, then converts |\n\nInput type is **auto-detected** from the argument: file extension for images/HTML, URL pattern for URLs, quoted text or unrecognized input for text descriptions.\n\n## Quick Start\n\n```bash\n# From an image (most common)\n/brewui:glm-design-to-code screenshot.png\n\n# From a text description\n/brewui:glm-design-to-code \"Dark landing page with hero section and pricing cards\"\n\n# From an existing HTML file\n/brewui:glm-design-to-code existing-page.html\n\n# From a URL (auto-screenshots via Playwright)\n/brewui:glm-design-to-code https://example.com/landing\n```\n\nCREATE mode converts your input to working, buildable code. You choose the framework (HTML, React, Flutter) and quality profile (max = pixel-perfect, optimal = balanced, efficient = fast).\n\n## Modes\n\n| Mode | Trigger | What it does |\n|------|---------|--------------|\n| **CREATE** | `screenshot.png` | Generates code from a design mockup (the main workflow) |\n| **REVIEW** | `--review original.png result.png` | Compares generated code (screenshot) against original design, scores quality (10-point scale), identifies gaps |\n| **FIX** | `--fix 'sidebar too narrow, wrong color'` | Uses review feedback to improve code iteratively (fix → re-screenshot → re-review cycle) |\n\n**Auto-detect:** Running `/brewui:glm-design-to-code` alone will ask you to choose a mode.\n\n## Examples\n\n### Good Usage\n\n```bash\n# Image input -- convert a Figma screenshot to HTML\n/brewui:glm-design-to-code mockup.png\n\n# Text input -- describe the UI you want\n/brewui:glm-design-to-code \"Minimalist dashboard with sidebar navigation and dark theme\"\n\n# HTML input -- improve existing code\n/brewui:glm-design-to-code legacy-page.html --framework react\n\n# URL input -- clone a live page\n/brewui:glm-design-to-code https://stripe.com/pricing --framework html\n\n# Generate React component with optimal quality (balanced speed/quality)\n/brewui:glm-design-to-code design.png --framework react --profile optimal\n\n# Review the generated code for pixel-perfectness\n/brewui:glm-design-to-code --review original.png generated.png\n\n# Fix issues found in review\n/brewui:glm-design-to-code --fix \"button should be blue not red, spacing too loose\"\n\n# Use Flutter and Z.ai with max quality\n/brewui:glm-design-to-code design.png --framework flutter --profile max --provider zai\n\n# Full CREATE → REVIEW → FIX cycle\n/brewui:glm-design-to-code design.png\n# ... generates code, optionally takes screenshot\n/brewui:glm-design-to-code --review original.png result.png\n# ... review shows issues, you get feedback\n/brewui:glm-design-to-code --fix \"fix the issues mentioned\"\n```\n\n### Common Mistakes\n\n```bash\n# WRONG: Providing a Figma URL (requires authentication, use exported PNG)\n/brewui:glm-design-to-code https://figma.com/design/abc...\n# FIX: Export the design as PNG first, or use a public URL\n\n# WRONG: Using --fix without prior REVIEW\n/brewui:glm-design-to-code --fix \"looks wrong\"\n# FIX: Run REVIEW mode first to get actionable feedback\n\n# WRONG: Specifying a framework the model doesn't know well\n/brewui:glm-design-to-code design.png --framework svelte\n# FIX: Use html, react, flutter, or custom. For other frameworks, use --framework custom\n```\n\n## Options\n\n### Core Arguments\n\n| Argument | Default | Options | Purpose |\n|----------|---------|---------|---------|\n| `input` | (required) | Image path, HTML path, URL, or text description | Input (type auto-detected) |\n| `--framework` | html | html, react, flutter, custom | Output code format |\n| `--profile` | max | max, optimal, efficient | Quality vs speed tradeoff |\n| `--provider` | zai | zai, openrouter | Which API to use |\n| `--output` | `./d2c-output` | Any directory path | Where to save generated files |\n| `--model` | (auto) | glm-5v-turbo, glm-4.6v, glm-4.6v-flash | Override model (auto-prefixed `z-ai/` for OpenRouter) |\n\n### Mode-Specific Arguments\n\n| Mode | Arguments | Purpose |\n|------|-----------|---------|\n| CREATE | (none) | Default behavior |\n| REVIEW | `--review original.png result.png` | Compare two images and score quality |\n| FIX | `--fix 'feedback text'` OR `--fix --review-file review.json` | Apply changes and regenerate |\n\n## Profiles\n\n| Profile | max_tokens | Quality | Speed | Cost | Best for |\n|---------|-----------|---------|-------|------|----------|\n| **max** | 32,768 | Pixel-perfect, all details | 30-60s | $0.05-0.08 | Complex UIs, high-fidelity design systems |\n| **optimal** | 16,384 | Good quality, most details | 15-30s | $0.03-0.05 | Production code, balanced approach |\n| **efficient** | 8,192 | Acceptable, basic structure | 5-15s | $0.01-0.03 | Quick prototypes, MVP code |\n\n## Output\n\nAfter CREATE completes, the following is created in `--output` directory (default: `./d2c-output`):\n\n**HTML Mode:**\n- `index.html` (240+ lines) – Semantic HTML5 structure\n- `styles.css` (400+ lines) – Complete styling with CSS custom properties\n- `script.js` (optional) – Interactive elements\n\n**React Mode:**\n- `package.json` – Vite project config\n- `src/App.jsx` – Root component\n- `src/components/` – Reusable UI components (Header, Sidebar, Button, etc.)\n- `src/styles/` – CSS Modules or Tailwind\n- Build verified with `npm run build` (Vite)\n\n**Flutter Mode:**\n- `pubspec.yaml` – Flutter dependencies\n- `lib/main.dart` – Entry point\n- `lib/screens/` – Page-level widgets\n- `lib/widgets/` – Reusable components\n- Build verified with `flutter run`\n\n## Providers & Pricing\n\n### Z.ai (Direct)\n\n**Recommended.** Zhipu AI's Z.ai API with GLM-5V-Turbo.\n\n- **Registration:** z.ai (Google/email signup, no phone required)\n- **Free tier:** ~20M tokens (~3 months of usage)\n- **Pricing:** $1.20/1M input, $4.00/1M output, $0.24/1M cached input\n- **Model:** `glm-5v-turbo` (202K context)\n- **Benchmark:** Design2Code 94.8 (highest quality)\n- **Typical cost per request:** $0.01–0.08 depending on profile\n\nSet `ZAI_API_KEY` environment variable:\n```bash\nexport ZAI_API_KEY=\"your-z-ai-api-key\"\n# Or save to .claude/.env or ~/.zshrc\n```\n\n### OpenRouter (Proxy)\n\nAlternative routing option. Same GLM models, same pricing, no free tier.\n\n- **Registration:** openrouter.ai\n- **Pricing:** Same as Z.ai ($1.20/$4.00)\n- **Model ID on OpenRouter:** `z-ai/glm-5v-turbo`\n- **Advantage:** Unified API for multiple model providers\n- **Disadvantage:** 1-2s latency overhead vs direct Z.ai\n\nSet `OPENROUTER_API_KEY` environment variable:\n```bash\nexport OPENROUTER_API_KEY=\"your-openrouter-key\"\n```\n\n## Tips\n\n- **Before CREATE:** Have a clear design mockup. Screenshots from Figma, Adobe XD, or Sketch work best.\n- **Use REVIEW early:** After CREATE, always run REVIEW to spot quality issues before iterating.\n- **FIX iteratively:** Each FIX cycle should address 2-3 specific issues. More iterations = better results.\n- **Choose framework wisely:** \n - **HTML** = Simple, static sites, fastest (no build)\n - **React** = Complex apps, component reuse, state management\n - **Flutter** = Cross-platform mobile/web, native feel\n - **Custom** = Any other framework (you guide the prompt)\n- **For high-fidelity designs:** Use `--profile max` for pixel-perfect output.\n- **For quick prototypes:** Use `--profile efficient` to save time and cost.\n- **Cache prompts:** Z.ai's cached input ($0.24/1M) is 5x cheaper than regular input. Repeated prompts automatically cache.\n\n## Documentation\n\nFull docs: [glm-design-to-code](https://doc-claude.brewcode.app/brewcode/skills/glm-design-to-code/)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8317,"content_sha256":"25252ee9b5876347204e470e46efca918f4f657419ae495b6fa8c779ae670d14"},{"filename":"references/context-flutter.md","content":"## Project context\n\n### Stack\n- Framework: Flutter 3.x\n- Language: Dart\n- Target: Web (flutter build web)\n\n### File structure convention\n- Entry point: lib/main.dart\n- Widgets in separate files: lib/widgets/widget_name.dart\n- Theme in: lib/theme.dart\n- Main page: lib/pages/home_page.dart\n\n### Component structure\nEach widget should be a separate file:\n- lib/widgets/header.dart\n- lib/widgets/sidebar.dart\n- lib/widgets/main_content.dart\n- lib/widgets/step_item.dart\n- lib/widgets/info_box.dart\n- etc.\n\n### Additional rules\n- Use StatelessWidget for layout components\n- Define all colors and text styles in lib/theme.dart as static constants\n- Use Column, Row, Expanded, Container, Padding for layout\n- Use SingleChildScrollView for scrollable content\n- Use Google Fonts or system font (no custom font files)\n- pubspec.yaml must include flutter SDK dependency\n- All styles inline via Flutter widget properties (Flutter does not use CSS)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":937,"content_sha256":"36c34b38be5ecbe5e11ed3ed0640f72534ae076e7dbe28779f7f5e7f18993603"},{"filename":"references/context-react.md","content":"## Project context\n\n### Stack\n- Framework: React 18 with JSX\n- CSS approach: CSS Modules (.module.css files)\n- Language: JavaScript (not TypeScript)\n\n### File structure convention\n- Components in separate files: ComponentName.jsx + ComponentName.module.css\n- Entry point: index.html that loads main.jsx via \u003cscript type=\"module\">\n- Use ES modules (import/export)\n\n### Component structure\nEach component should be a separate file pair:\n- Header.jsx + Header.module.css\n- Sidebar.jsx + Sidebar.module.css\n- MainContent.jsx + MainContent.module.css\n- etc.\n\n### Additional rules\n- Use React.createElement or JSX (assume Babel/build step will handle JSX)\n- Export each component as default\n- Import CSS modules as `import styles from './Component.module.css'`\n- Use className={styles.className} pattern\n- App.jsx is the root component that composes all others\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":855,"content_sha256":"8b5105ad18bb315395591b7d74d941a1aa1cdc6aa390184c53a34952d8133a7e"},{"filename":"references/context-template.md","content":"## Project context\n\n### Stack\n- Framework: {{FRAMEWORK}}\n- CSS approach: {{CSS_APPROACH}}\n- Language: {{LANGUAGE}}\n\n### Existing components (reuse these, do NOT recreate)\n{{COMPONENTS_LIST}}\n\n### Design tokens\n{{DESIGN_TOKENS}}\n\n### File structure convention\n{{FILE_STRUCTURE}}\n\n### Additional rules\n{{PROJECT_RULES}}\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":318,"content_sha256":"f135fa26b587fd2faf879db94c8dff27e2ba5442d27ede852db5c21ba79eb22d"},{"filename":"references/profile-efficient.md","content":"You are a frontend developer. Follow the task instruction. Produce working code.\n\n## Output format\n\nWrap every file in markers. Output markers and file content only — no text before, between, or after.\n\n===FILE: path/file.ext===\ncontent\n===END_FILE===\n\nWrong (adds backticks): ```html\\n===FILE: index.html===\nCorrect: ===FILE: index.html===\n\n## Requirements\n\n- Match design: colors, layout, typography\n- Semantic HTML5, entry: index.html, CSS in separate .css file\n- CDN excluded, inline styles excluded\n- All visible text content preserved\n\nOutput starts with ===FILE: and ends with ===END_FILE===. Nothing else.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":616,"content_sha256":"c8c9d5b2543bbb3179dbc28bdc22ca94cf130a0eff684bb8f5ef5235c2ea3b92"},{"filename":"references/profile-max.md","content":"You are a world-class frontend developer. Follow the task instruction precisely.\n\n## Output format\n\nWrap every file in markers. Output markers and file content only — no text before, between, or after.\n\n===FILE: path/to/file.ext===\ncontent\n===END_FILE===\n\nWrong (adds backticks): ```html\\n===FILE: index.html===\nCorrect: ===FILE: index.html===\n\n## Requirements\n\n- When reproducing: exact colors (eyedropper precision), exact spacing ratios, exact font sizes, exact border-radius values. When creating from sketches: professional palette, consistent spacing, polished typography\n- Measure every element from screenshot: header height, sidebar width, margins, section padding\n- CSS custom properties for all colors, spacing, and typography extracted from the design\n- Semantic HTML5, entry point: index.html\n- CSS in separate .css file(s) — inline styles and `\u003cstyle>` tags excluded\n- JS in separate .js file(s) for interactive elements\n- CDN dependencies excluded unless specified in project context\n- All text content preserved verbatim — URLs, table data, code snippets, descriptions intact\n- Exact layout proportions: sidebar-to-content ratio, header height, section spacing\n- All visual details reproduced: icons, badges, borders, shadows, gradients, hover states\n- Code blocks use monospace font matching exact background color from design\n- Tables match exact column widths and cell padding\n- Info/alert boxes match exact background color, border color, icon style, border-radius\n\nOutput starts with ===FILE: and ends with ===END_FILE===. Nothing else.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1564,"content_sha256":"1b6536ce45b6c05e306c9d6bc667586c74f2a1ea7bed3aa82c79443b1aac4a2b"},{"filename":"references/profile-optimal.md","content":"You are a skilled frontend developer. Follow the task instruction and produce clean, accurate code.\n\n## Output format\n\nWrap every file in markers. Output markers and file content only — no text before, between, or after.\n\n===FILE: path/to/file.ext===\ncontent\n===END_FILE===\n\nWrong (adds backticks): ```html\\n===FILE: index.html===\nCorrect: ===FILE: index.html===\n\n## Requirements\n\n- Match design: correct colors, proportions, typography, layout structure\n- CSS custom properties for colors\n- Semantic HTML5, entry point: index.html\n- CSS in separate .css file(s) — inline styles excluded\n- JS in separate .js file(s) if needed\n- CDN dependencies excluded unless specified in project context\n- All text content from screenshot preserved verbatim\n- Layout structure and proportions matched (sidebar, header, content areas)\n\nOutput starts with ===FILE: and ends with ===END_FILE===. Nothing else.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":898,"content_sha256":"06abeebb0b426b9791e8ee4c8d5234c026d228c96e19086e3b65b22fe4af47e8"},{"filename":"references/review.md","content":"Compare two images:\n1. FIRST image: original design mockup\n2. SECOND image: screenshot of generated code rendered in a browser\n\nRate visual fidelity 1-10 and list specific differences.\n\n===REVIEW===\nscore: N/10\nsummary: one-line summary\n\ndifferences:\n- [area] description of mismatch\n\nsuggestions:\n- specific fix suggestion\n===END_REVIEW===\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":341,"content_sha256":"140615e9a46851b11b133b3ca4faaaceb3d75566fce4fb79772e0686624c2902"},{"filename":"scripts/glm-build-request.sh","content":"#!/bin/sh\n# glm-build-request.sh — Build JSON request payload for GLM vision API\n# Usage: glm-build-request.sh \u003cimage_path> \u003cprompt_file> [context_file] [model] [max_tokens] [temperature] [top_p] [instruction] [html_source]\n# Output: JSON payload to stdout\n# Requires: jq, base64\n# Prompt file is used as SYSTEM message (cached by Z.ai). Context is appended to USER message with the image.\n\nset -e\n\nIMAGE_PATH=\"${1:?Usage: glm-build-request.sh \u003cimage> \u003cprompt> [context] [model] [max_tokens] [temp] [top_p]}\"\nPROMPT_FILE=\"${2:?Usage: glm-build-request.sh \u003cimage> \u003cprompt> [context] [model] [max_tokens] [temp] [top_p]}\"\nCONTEXT_FILE=\"${3:-}\"\nMODEL=\"${4:-glm-5v-turbo}\"\nMAX_TOKENS=\"${5:-32768}\"\nTEMPERATURE=\"${6:-0.2}\"\nTOP_P=\"${7:-0.85}\"\nCUSTOM_INSTRUCTION=\"${8:-}\"\nHTML_SOURCE=\"${9:-}\"\n\ncommand -v jq >/dev/null 2>&1 || { echo \"ERROR: jq is required\" >&2; exit 1; }\ncommand -v base64 >/dev/null 2>&1 || { echo \"ERROR: base64 is required\" >&2; exit 1; }\n\n[ -f \"$IMAGE_PATH\" ] || { echo \"ERROR: Image not found: $IMAGE_PATH\" >&2; exit 1; }\n[ -f \"$PROMPT_FILE\" ] || { echo \"ERROR: Prompt not found: $PROMPT_FILE\" >&2; exit 1; }\n\ncase \"$IMAGE_PATH\" in\n *.png) MIME=\"image/png\" ;;\n *.jpg|*.jpeg) MIME=\"image/jpeg\" ;;\n *.webp) MIME=\"image/webp\" ;;\n *.gif) MIME=\"image/gif\" ;;\n *) echo \"ERROR: Unsupported image format: $IMAGE_PATH\" >&2; exit 1 ;;\nesac\n\nSYSTEM_TEXT=$(cat \"$PROMPT_FILE\")\n\nif [ -n \"$CUSTOM_INSTRUCTION\" ]; then\n USER_TEXT=\"$CUSTOM_INSTRUCTION\"\nelse\n USER_TEXT=\"Convert this design screenshot to working code files.\"\nfi\nif [ -n \"$CONTEXT_FILE\" ] && [ -f \"$CONTEXT_FILE\" ]; then\n CONTEXT_TEXT=$(cat \"$CONTEXT_FILE\")\n USER_TEXT=\"${USER_TEXT}\n\n${CONTEXT_TEXT}\"\nfi\n\n# base64 encode — portable: use stdin redirect + strip newlines (works on Linux and macOS)\nB64=$(base64 \u003c \"$IMAGE_PATH\" | tr -d '\\n')\nDATA_URI=\"data:${MIME};base64,${B64}\"\n\n# Write data URI to temp file to avoid ARG_MAX for large images\nTMPURI=$(mktemp)\nprintf '%s' \"$DATA_URI\" > \"$TMPURI\"\n\n# Write user text to temp file (ARG_MAX safety)\nTMPUSER=$(mktemp)\nprintf '%s' \"$USER_TEXT\" > \"$TMPUSER\"\n\n# Prepare HTML source temp file if provided\nTMPHTML=\"\"\nif [ -n \"$HTML_SOURCE\" ] && [ -f \"$HTML_SOURCE\" ]; then\n TMPHTML=$(mktemp)\n cp \"$HTML_SOURCE\" \"$TMPHTML\"\nfi\n\ntrap \"rm -f '$TMPURI' '$TMPUSER' '$TMPHTML'\" EXIT\n\nif [ -n \"$TMPHTML\" ]; then\n jq -n \\\n --arg model \"$MODEL\" \\\n --arg system \"$SYSTEM_TEXT\" \\\n --rawfile user_text \"$TMPUSER\" \\\n --rawfile data_uri \"$TMPURI\" \\\n --rawfile html_source \"$TMPHTML\" \\\n --argjson max_tokens \"$MAX_TOKENS\" \\\n --argjson temperature \"$TEMPERATURE\" \\\n --argjson top_p \"$TOP_P\" \\\n '{\n model: $model,\n temperature: $temperature,\n top_p: $top_p,\n max_tokens: $max_tokens,\n messages: [\n { role: \"system\", content: $system },\n { role: \"user\", content: [\n { type: \"text\", text: ($user_text | rtrimstr(\"\\n\")) },\n { type: \"image_url\", image_url: { url: ($data_uri | rtrimstr(\"\\n\")) } },\n { type: \"text\", text: (\"--- HTML SOURCE ---\\n\" + ($html_source | rtrimstr(\"\\n\"))) }\n ]}\n ]\n }'\nelse\n jq -n \\\n --arg model \"$MODEL\" \\\n --arg system \"$SYSTEM_TEXT\" \\\n --rawfile user_text \"$TMPUSER\" \\\n --rawfile data_uri \"$TMPURI\" \\\n --argjson max_tokens \"$MAX_TOKENS\" \\\n --argjson temperature \"$TEMPERATURE\" \\\n --argjson top_p \"$TOP_P\" \\\n '{\n model: $model,\n temperature: $temperature,\n top_p: $top_p,\n max_tokens: $max_tokens,\n messages: [\n { role: \"system\", content: $system },\n { role: \"user\", content: [\n { type: \"text\", text: ($user_text | rtrimstr(\"\\n\")) },\n { type: \"image_url\", image_url: { url: ($data_uri | rtrimstr(\"\\n\")) } }\n ]}\n ]\n }'\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":3753,"content_sha256":"c76eb4763e5abcce5b4030789bb67930248f50adb152c7d77e958125f8a33cd4"},{"filename":"scripts/glm-build-text-request.sh","content":"#!/bin/sh\n# glm-build-text-request.sh — Build JSON request payload for GLM text API (no image)\n# Usage: glm-build-text-request.sh \u003cuser_text_or_file> \u003cprompt_file> [context_file] [model] [max_tokens] [temperature] [top_p] [instruction]\n# Output: JSON payload to stdout\n# Requires: jq\n\nset -e\n\nUSER_INPUT=\"${1:?Usage: glm-build-text-request.sh \u003ctext_or_file> \u003cprompt> [context] [model] [max_tokens] [temp] [top_p]}\"\nPROMPT_FILE=\"${2:?Usage: glm-build-text-request.sh \u003ctext_or_file> \u003cprompt> [context] [model] [max_tokens] [temp] [top_p]}\"\nCONTEXT_FILE=\"${3:-}\"\nMODEL=\"${4:-glm-5v-turbo}\"\nMAX_TOKENS=\"${5:-32768}\"\nTEMPERATURE=\"${6:-0.2}\"\nTOP_P=\"${7:-0.85}\"\nCUSTOM_INSTRUCTION=\"${8:-}\"\n\ncommand -v jq >/dev/null 2>&1 || { echo \"ERROR: jq is required\" >&2; exit 1; }\n[ -f \"$PROMPT_FILE\" ] || { echo \"ERROR: Prompt not found: $PROMPT_FILE\" >&2; exit 1; }\n\nSYSTEM_TEXT=$(cat \"$PROMPT_FILE\")\n\n# If CUSTOM_INSTRUCTION is set, use it as prefix; otherwise use defaults\nif [ -n \"$CUSTOM_INSTRUCTION\" ]; then\n if [ -f \"$USER_INPUT\" ]; then\n USER_TEXT=\"${CUSTOM_INSTRUCTION}\n\n$(cat \"$USER_INPUT\")\"\n else\n USER_TEXT=\"${CUSTOM_INSTRUCTION}\n\n$USER_INPUT\"\n fi\nelse\n if [ -f \"$USER_INPUT\" ]; then\n USER_TEXT=\"Convert this code to working frontend code files:\n\n$(cat \"$USER_INPUT\")\"\n else\n USER_TEXT=\"Create working frontend code files based on this description:\n\n$USER_INPUT\"\n fi\nfi\n\nif [ -n \"$CONTEXT_FILE\" ] && [ -f \"$CONTEXT_FILE\" ]; then\n CONTEXT_TEXT=$(cat \"$CONTEXT_FILE\")\n USER_TEXT=\"${USER_TEXT}\n\n${CONTEXT_TEXT}\"\nfi\n\n# Write user text to temp file (ARG_MAX safety for large HTML files)\nTMPUSER=$(mktemp)\ntrap \"rm -f '$TMPUSER'\" EXIT\nprintf '%s' \"$USER_TEXT\" > \"$TMPUSER\"\n\njq -n \\\n --arg model \"$MODEL\" \\\n --arg system \"$SYSTEM_TEXT\" \\\n --rawfile user_text \"$TMPUSER\" \\\n --argjson max_tokens \"$MAX_TOKENS\" \\\n --argjson temperature \"$TEMPERATURE\" \\\n --argjson top_p \"$TOP_P\" \\\n '{\n model: $model,\n temperature: $temperature,\n top_p: $top_p,\n max_tokens: $max_tokens,\n messages: [\n { role: \"system\", content: $system },\n { role: \"user\", content: ($user_text | rtrimstr(\"\\n\")) }\n ]\n }'\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2131,"content_sha256":"173c57ccdef8f1b4780b970dea94a4ccea48e91ec3f63a97358494c337deac97"},{"filename":"scripts/glm-extract.sh","content":"#!/bin/sh\n# glm-extract.sh — Extract files from GLM API response\n# Usage: glm-extract.sh \u003cresponse.json> \u003coutput_dir>\n# Parses ===FILE: path=== ... ===END_FILE=== markers from response content\n# Falls back to single index.html if no markers found\n\nset -e\n\nRESPONSE=\"${1:?Usage: glm-extract.sh \u003cresponse.json> \u003coutput_dir>}\"\nOUTPUT_DIR=\"${2:?Usage: glm-extract.sh \u003cresponse.json> \u003coutput_dir>}\"\n\n[ -f \"$RESPONSE\" ] || { echo \"ERROR: Response not found: $RESPONSE\" >&2; exit 1; }\n\n# Validate OUTPUT_DIR has no dangerous shell metacharacters\ncase \"$OUTPUT_DIR\" in\n *[\\'\\\"\\`\\$\\;\\|\\&\\(\\)\\{\\}\\[\\]\\#\\!\\~\\\\]*)\n echo \"ERROR: OUTPUT_DIR contains unsafe characters: $OUTPUT_DIR\" >&2\n exit 1\n ;;\nesac\n\nCONTENT=$(jq -r '.choices[0].message.content // empty' \"$RESPONSE\")\n\nif [ -z \"$CONTENT\" ]; then\n echo \"ERROR: No content in response\" >&2\n exit 1\nfi\n\nmkdir -p \"$OUTPUT_DIR\"\n\nif printf '%s\\n' \"$CONTENT\" | grep -q '===FILE:'; then\n # Extract content to temp file to avoid shell escaping issues\n TMPFILE=$(mktemp)\n trap \"rm -f '$TMPFILE'\" EXIT\n jq -r '.choices[0].message.content' \"$RESPONSE\" > \"$TMPFILE\"\n\n awk -v outdir=\"$OUTPUT_DIR\" '\n /^===FILE: / {\n fname = $0\n sub(/^===FILE: */, \"\", fname)\n sub(/ *===.*$/, \"\", fname)\n sub(/=+$/, \"\", fname)\n # Sanitize: only allow safe chars in filenames\n gsub(/[^a-zA-Z0-9._\\/\\-]/, \"\", fname)\n gsub(/^\\/+/, \"\", fname)\n # Reject any path with .. (traversal attempt)\n if (fname ~ /\\.\\./) { next }\n if (fname == \"\") { next }\n current_file = outdir \"/\" fname\n writing = 1\n next\n }\n /^===END_FILE===/ {\n if (writing && current_file != \"\") {\n close(current_file)\n file_count++\n print \" \" fname \" (\" lines \" lines)\" > \"/dev/stderr\"\n lines = 0\n }\n writing = 0\n next\n }\n writing {\n # Ensure parent directory exists on first write\n if (lines == 0) {\n dir = current_file\n sub(/\\/[^\\/]*$/, \"\", dir)\n gsub(/'\\''/,\"'\\''\\\\'\\'''\\''\", dir)\n cmd = \"mkdir -p '\\''\" dir \"'\\''\"\n system(cmd)\n close(cmd)\n printf \"\" > current_file\n close(current_file)\n }\n print >> current_file\n lines++\n }\n END {\n if (writing && current_file != \"\") {\n close(current_file)\n print \"WARNING: Truncated file (no ===END_FILE===): \" fname > \"/dev/stderr\"\n }\n print \"Extracted \" file_count \" file(s)\" > \"/dev/stderr\"\n }\n ' \"$TMPFILE\"\nelse\n echo \"No ===FILE: markers found. Trying code block extraction...\" >&2\n\n # Extract all fenced code blocks with language tags\n BLOCK_NUM=0\n printf '%s\\n' \"$CONTENT\" | awk -v outdir=\"$OUTPUT_DIR\" '\n BEGIN {\n # Language to default filename mapping\n map[\"html\"] = \"index.html\"\n map[\"htm\"] = \"index.html\"\n map[\"css\"] = \"styles.css\"\n map[\"js\"] = \"script.js\"\n map[\"javascript\"] = \"script.js\"\n map[\"jsx\"] = \"App.jsx\"\n map[\"tsx\"] = \"App.tsx\"\n map[\"ts\"] = \"main.ts\"\n map[\"typescript\"] = \"main.ts\"\n map[\"dart\"] = \"main.dart\"\n map[\"yaml\"] = \"pubspec.yaml\"\n map[\"yml\"] = \"pubspec.yaml\"\n map[\"json\"] = \"package.json\"\n map[\"\"] = \"index.html\"\n }\n /^```[a-zA-Z]/ {\n lang = $0\n sub(/^```/, \"\", lang)\n sub(/[^a-zA-Z0-9].*/, \"\", lang)\n lang = tolower(lang)\n in_block = 1\n content = \"\"\n next\n }\n /^```$/ && in_block {\n in_block = 0\n if (content != \"\") {\n # Determine filename\n base = map[lang]\n if (base == \"\") base = \"file.\" lang\n\n # Handle duplicates\n if (seen[base]++) {\n ext_pos = index(base, \".\")\n if (ext_pos > 0) {\n name_part = substr(base, 1, ext_pos - 1)\n ext_part = substr(base, ext_pos)\n base = name_part seen[base] ext_part\n } else {\n base = base seen[base]\n }\n }\n\n fname = outdir \"/\" base\n printf \"%s\", content > fname\n close(fname)\n lines_count = split(content, arr, \"\\n\") - 1\n print \" \" base \" (\" lines_count \" lines)\" > \"/dev/stderr\"\n file_count++\n }\n next\n }\n in_block {\n content = content $0 \"\\n\"\n }\n END {\n if (file_count > 0) {\n print \"Extracted \" file_count \" file(s) from code blocks\" > \"/dev/stderr\"\n }\n }\n '\n\n # Check if any files were extracted\n EXTRACTED=$(find \"$OUTPUT_DIR\" -type f 2>/dev/null | wc -l | tr -d ' ')\n\n if [ \"$EXTRACTED\" -eq 0 ]; then\n echo \"WARNING: No code blocks found. Saving raw content as index.html\" >&2\n printf '%s\\n' \"$CONTENT\" > \"$OUTPUT_DIR/index.html\"\n echo \" index.html ($(printf '%s\\n' \"$CONTENT\" | wc -l | tr -d ' ') lines)\" >&2\n echo \"Extracted 1 file(s) (raw fallback)\" >&2\n fi\nfi\n\necho \"\" >&2\necho \"Output directory: $OUTPUT_DIR\" >&2\nls -la \"$OUTPUT_DIR\" >&2\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":4643,"content_sha256":"9cb08c51f3827de5badc83cbc9a2ec32c4aa35b1107df17d1de32910d9c88afc"},{"filename":"scripts/glm-request.sh","content":"#!/bin/sh\n# glm-request.sh — Send request to GLM API (Z.ai or OpenRouter)\n# Usage: glm-request.sh \u003cpayload.json> \u003coutput.json> [provider]\n# Provider: zai (default) | openrouter\n# Env vars: ZAI_API_KEY, OPENROUTER_API_KEY\n# Output: raw API response saved to output.json, status info to stderr\n\nset -e\n\nPAYLOAD=\"${1:?Usage: glm-request.sh \u003cpayload.json> \u003coutput.json> [provider]}\"\nOUTPUT=\"${2:?Usage: glm-request.sh \u003cpayload.json> \u003coutput.json> [provider]}\"\nPROVIDER=\"${3:-zai}\"\n\n[ -f \"$PAYLOAD\" ] || { echo \"ERROR: Payload not found: $PAYLOAD\" >&2; exit 1; }\n\n# Validate payload is valid JSON\njq empty \"$PAYLOAD\" 2>/dev/null || { echo \"ERROR: Invalid JSON in $PAYLOAD\" >&2; exit 1; }\n\n# Set API endpoint and key\ncase \"$PROVIDER\" in\n zai)\n API_URL=\"https://api.z.ai/api/paas/v4/chat/completions\"\n API_KEY=\"${ZAI_API_KEY:?ERROR: ZAI_API_KEY not set}\"\n ;;\n openrouter)\n API_URL=\"https://openrouter.ai/api/v1/chat/completions\"\n API_KEY=\"${OPENROUTER_API_KEY:?ERROR: OPENROUTER_API_KEY not set}\"\n ;;\n *)\n echo \"ERROR: Unknown provider: $PROVIDER (use: zai, openrouter)\" >&2\n exit 1\n ;;\nesac\n\necho \"Sending to $PROVIDER ($API_URL)...\" >&2\necho \"Model: $(jq -r '.model' \"$PAYLOAD\")\" >&2\necho \"Max tokens: $(jq -r '.max_tokens' \"$PAYLOAD\")\" >&2\n\n# Send request with retry\nif [ \"$PROVIDER\" = \"openrouter\" ]; then\n HTTP_CODE=$(curl -s -w \"%{http_code}\" -o \"$OUTPUT\" \\\n --retry 3 --retry-delay 5 --retry-max-time 60 \\\n --max-time 600 \\\n -X POST \"$API_URL\" \\\n -H \"Authorization: Bearer $API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"HTTP-Referer: https://brewcode.pt\" \\\n -H \"X-Title: brewcode-glm\" \\\n -d @\"$PAYLOAD\")\nelse\n HTTP_CODE=$(curl -s -w \"%{http_code}\" -o \"$OUTPUT\" \\\n --retry 3 --retry-delay 5 --retry-max-time 60 \\\n --max-time 600 \\\n -X POST \"$API_URL\" \\\n -H \"Authorization: Bearer $API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d @\"$PAYLOAD\")\nfi\n\necho \"HTTP: $HTTP_CODE\" >&2\n\n# Check HTTP status\nif [ \"$HTTP_CODE\" -lt 200 ] || [ \"$HTTP_CODE\" -ge 300 ]; then\n echo \"ERROR: API returned HTTP $HTTP_CODE\" >&2\n cat \"$OUTPUT\" >&2\n exit 1\nfi\n\n# Check for API errors in response\nif jq -e '.error' \"$OUTPUT\" >/dev/null 2>&1; then\n echo \"ERROR: API error in response:\" >&2\n jq '.error' \"$OUTPUT\" >&2\n exit 1\nfi\n\n# Print usage stats\nFINISH=$(jq -r '.choices[0].finish_reason // \"unknown\"' \"$OUTPUT\")\nIN_TOK=$(jq -r '.usage.prompt_tokens // \"?\"' \"$OUTPUT\")\nOUT_TOK=$(jq -r '.usage.completion_tokens // \"?\"' \"$OUTPUT\")\nREASON_TOK=$(jq -r '.usage.completion_tokens_details.reasoning_tokens // 0' \"$OUTPUT\")\n\necho \"Finish: $FINISH\" >&2\necho \"Tokens: in=$IN_TOK out=$OUT_TOK reasoning=$REASON_TOK\" >&2\necho \"Response saved: $OUTPUT ($(wc -c \u003c \"$OUTPUT\" | tr -d ' ') bytes)\" >&2\n\n# Warn if truncated\nif [ \"$FINISH\" = \"length\" ]; then\n echo \"WARNING: Response was truncated (hit max_tokens limit)\" >&2\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2884,"content_sha256":"45a48ac085f545630baec0ff5cd16ffa4d986611a32238a6320c0d8ddfdd70d9"},{"filename":"scripts/glm-verify.sh","content":"#!/bin/sh\n# glm-verify.sh — Serve generated HTML and output URL for Playwright\n# Usage: glm-verify.sh \u003chtml_dir> [port]\n# Starts HTTP server, outputs URL, waits for Ctrl+C\n\nset -e\n\nPID_FILE=\"/tmp/d2c-server.pid\"\nTIMER_PID_FILE=\"/tmp/d2c-timer.pid\"\n\nif [ \"${1:-}\" = \"--kill\" ]; then\n if [ -f \"$TIMER_PID_FILE\" ]; then\n kill \"$(cat \"$TIMER_PID_FILE\")\" 2>/dev/null\n rm -f \"$TIMER_PID_FILE\"\n fi\n if [ -f \"$PID_FILE\" ]; then\n PID=$(cat \"$PID_FILE\")\n kill \"$PID\" 2>/dev/null && echo \"Server $PID stopped\" >&2 || echo \"Server $PID not running\" >&2\n rm -f \"$PID_FILE\"\n else\n echo \"No PID file found\" >&2\n fi\n exit 0\nfi\n\nHTML_DIR=\"${1:?Usage: glm-verify.sh \u003chtml_dir> [port]}\"\nPORT=\"${2:-8900}\"\n\ncase \"$PORT\" in\n *[!0-9]*) echo \"ERROR: Invalid port: $PORT\" >&2; exit 1 ;;\nesac\n\n# Find entry point\nif [ -f \"$HTML_DIR/build/web/index.html\" ]; then\n SERVE_DIR=\"$HTML_DIR/build/web\"\nelif [ -f \"$HTML_DIR/dist/index.html\" ]; then\n SERVE_DIR=\"$HTML_DIR/dist\"\nelif [ -f \"$HTML_DIR/index.html\" ]; then\n SERVE_DIR=\"$HTML_DIR\"\nelse\n echo \"ERROR: No index.html found in $HTML_DIR (checked build/web/, dist/, root)\" >&2\n exit 1\nfi\n\nABS_DIR=$(cd \"$SERVE_DIR\" && pwd)\n\necho \"Serving: $ABS_DIR\" >&2\necho \"Port: $PORT\" >&2\n\n(cd \"$ABS_DIR\" && python3 -m http.server \"$PORT\") &\nSERVER_PID=$!\nsleep 1\n\n# Verify server started\nif ! kill -0 \"$SERVER_PID\" 2>/dev/null; then\n echo \"ERROR: Failed to start server\" >&2\n exit 1\nfi\n\necho \"http://localhost:$PORT/\"\n\necho \"$SERVER_PID\" > \"$PID_FILE\"\n\n(sleep 60 && kill \"$SERVER_PID\" 2>/dev/null && rm -f \"$PID_FILE\" && rm -f \"$TIMER_PID_FILE\") &\nTIMER_PID=$!\necho \"$TIMER_PID\" > \"$TIMER_PID_FILE\"\n\necho \"Server PID: $SERVER_PID (kill with: $0 --kill)\" >&2\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1702,"content_sha256":"b160e01966963a508d24606f289331b96fee42e7ee4a8049307a87306bce1cef"},{"filename":"scripts/parse-args.sh","content":"#!/bin/sh\n# parse-args.sh — Parse glm-design-to-code skill arguments\n# Usage: parse-args.sh [args...]\n# Output: KEY=VALUE pairs to stdout\n\nset -e\n\nIMAGE=\"\"\nRESULT_IMAGE=\"\"\nINPUT_TYPE=\"\"\nFRAMEWORK=\"html\"\nPROFILE=\"max\"\nPROVIDER=\"zai\"\nOUTPUT=\"./d2c-output\"\nREVIEW=\"false\"\nMODE=\"create\"\nFIX_TEXT=\"\"\nREVIEW_FILE=\"\"\nMODEL=\"\"\nMAX_TOKENS=\"\"\n\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n --framework|-f)\n FRAMEWORK=\"${2:?--framework requires value: html|react|flutter|custom}\"\n shift 2\n ;;\n --profile|-p)\n PROFILE=\"${2:?--profile requires value: max|optimal|efficient}\"\n shift 2\n ;;\n --provider)\n PROVIDER=\"${2:?--provider requires value: zai|openrouter}\"\n shift 2\n ;;\n --output|-o)\n OUTPUT=\"${2:?--output requires value: directory path}\"\n shift 2\n ;;\n --review|-r)\n MODE=\"review\"\n REVIEW=\"true\"\n shift\n ;;\n --fix)\n MODE=\"fix\"\n # Check if next arg is a value (not a flag)\n if [ $# -gt 1 ] && [ \"${2#-}\" = \"$2\" ]; then\n FIX_TEXT=\"$2\"\n shift\n fi\n shift\n ;;\n --review-file)\n REVIEW_FILE=\"${2:?--review-file requires a path}\"\n shift 2\n ;;\n --model|-m)\n MODEL=\"${2:?--model requires a model ID}\"\n shift 2\n ;;\n --*)\n echo \"WARNING: Unknown flag: $1\" >&2\n shift\n ;;\n *)\n if [ -z \"$IMAGE\" ]; then\n IMAGE=\"$1\"\n elif [ -z \"$RESULT_IMAGE\" ]; then\n RESULT_IMAGE=\"$1\"\n else\n echo \"WARNING: Extra argument ignored: $1\" >&2\n fi\n shift\n ;;\n esac\ndone\n\n# Detect input type from IMAGE value\nif [ -n \"$IMAGE\" ]; then\n case \"$IMAGE\" in\n http://*|https://*)\n INPUT_TYPE=\"url\"\n ;;\n *.png|*.jpg|*.jpeg|*.webp|*.gif)\n INPUT_TYPE=\"image\"\n ;;\n *.html|*.htm)\n INPUT_TYPE=\"html\"\n ;;\n *)\n # If it's a file that exists and is an image, treat as image\n if [ -f \"$IMAGE\" ] && file --mime-type \"$IMAGE\" 2>/dev/null | grep -qE ': image/'; then\n INPUT_TYPE=\"image\"\n elif [ -f \"$IMAGE\" ]; then\n # Existing file but not image — treat as HTML/text file\n INPUT_TYPE=\"html\"\n else\n # Not a file, not a URL — treat as text description\n INPUT_TYPE=\"text\"\n fi\n ;;\n esac\nfi\n\n# Validate framework\ncase \"$FRAMEWORK\" in\n html|react|flutter|custom) ;;\n *) echo \"ERROR: Invalid framework: $FRAMEWORK (use: html, react, flutter, custom)\" >&2; exit 1 ;;\nesac\n\n# Validate profile\ncase \"$PROFILE\" in\n max|optimal|efficient) ;;\n *) echo \"ERROR: Invalid profile: $PROFILE (use: max, optimal, efficient)\" >&2; exit 1 ;;\nesac\n\n# Map profile to max_tokens\ncase \"$PROFILE\" in\n max) MAX_TOKENS=32768 ;;\n optimal) MAX_TOKENS=16384 ;;\n efficient) MAX_TOKENS=8192 ;;\nesac\n\n# Validate provider\ncase \"$PROVIDER\" in\n zai|openrouter) ;;\n *) echo \"ERROR: Invalid provider: $PROVIDER (use: zai, openrouter)\" >&2; exit 1 ;;\nesac\n\necho \"IMAGE=$IMAGE\"\necho \"FRAMEWORK=$FRAMEWORK\"\necho \"PROFILE=$PROFILE\"\necho \"PROVIDER=$PROVIDER\"\necho \"OUTPUT=$OUTPUT\"\necho \"REVIEW=$REVIEW\"\necho \"MODE=$MODE\"\necho \"FIX_TEXT=$FIX_TEXT\"\necho \"RESULT_IMAGE=$RESULT_IMAGE\"\necho \"REVIEW_FILE=$REVIEW_FILE\"\necho \"MODEL=$MODEL\"\necho \"INPUT_TYPE=$INPUT_TYPE\"\necho \"MAX_TOKENS=$MAX_TOKENS\"\n\nif [ -z \"$IMAGE\" ]; then\n echo \"IMAGE_MISSING=true\"\n echo \"NOTE: No screenshot path provided. Will ask user.\" >&2\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":3371,"content_sha256":"c36df51c1ab353c958090620b7b8aa67b110e95225cc34d3396be8b2924b5d1a"}],"content_json":{"type":"doc","content":[{"type":"paragraph","content":[{"text":"\u003cinstructions>","type":"text"}]},{"type":"heading","attrs":{"level":1},"content":[{"text":"GLM Design-to-Code","type":"text"}]},{"type":"paragraph","content":[{"text":"Converts design inputs (screenshots, text descriptions, HTML files, URLs) to working frontend code using GLM vision models. Three modes: CREATE, REVIEW, FIX.","type":"text"}]},{"type":"paragraph","content":[{"text":"Arguments:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"$ARGUMENTS","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Mode Routing","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Mode","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flow","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CREATE","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Phase 0 → 0.5 → 1 → 2 → 3 (with auto-fix) → 4 (mandatory verify) → 5 (if --review)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"REVIEW","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Phase 0 → 0.5 → 1 → 5","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"FIX","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Phase 0 → 0.5 → 1 → 6","type":"text"}]}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"PARAMETER PRIORITY:","type":"text","marks":[{"type":"strong"}]},{"text":" User prompt arguments ALWAYS override defaults and environment.","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Explicit flags in ","type":"text"},{"text":"$ARGUMENTS","type":"text","marks":[{"type":"code_inline"}]},{"text":" (","type":"text"},{"text":"--model","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--profile","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--provider","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--framework","type":"text","marks":[{"type":"code_inline"}]},{"text":") → highest priority","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"API keys from ","type":"text"},{"text":"$ARGUMENTS","type":"text","marks":[{"type":"code_inline"}]},{"text":" prompt text (if user pasted a key inline) → override ","type":"text"},{"text":".env","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Environment variables (","type":"text"},{"text":".env","type":"text","marks":[{"type":"code_inline"}]},{"text":", shell env) → fallback","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Defaults from ","type":"text"},{"text":"parse-args.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" → lowest priority","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"MANDATORY OUTPUT:","type":"text","marks":[{"type":"strong"}]},{"text":" Before ANY API call, output the full resolved configuration table (see Step 2.5 in Phase 2). This applies to ALL modes (CREATE, REVIEW, FIX). The user must always see what was resolved from their input.","type":"text"}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 0: Parse Arguments and Gather Config","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Parse Flags","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"bash \"${CLAUDE_SKILL_DIR}/scripts/parse-args.sh\" \"$ARGUMENTS\" && echo \"OK\" || echo \"FAILED\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Output: key=value pairs. Store all values.","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Also scan ","type":"text","marks":[{"type":"strong"}]},{"text":"$ARGUMENTS","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" raw text","type":"text","marks":[{"type":"strong"}]},{"text":" for any inline values not captured by flags:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"API key pasted in prompt text → extract and use (overrides ","type":"text"},{"text":".env","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Model name mentioned in free text (e.g., \"use glm-4.6v\") → treat as ","type":"text"},{"text":"--model","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Profile/provider mentioned in text → treat as flags","type":"text"}]}]}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Key","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Default","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Options","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"IMAGE","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"(required)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Path to screenshot file, URL, HTML file, or text description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"INPUT_TYPE","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"auto","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"image, html, text, url","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"FRAMEWORK","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"html","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"html, react, flutter, custom","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"PROFILE","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"max","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"max, optimal, efficient","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"PROVIDER","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"zai","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"zai, openrouter","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"OUTPUT","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./d2c-output","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Output directory","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"REVIEW","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"false","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"true/false","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MODE","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"create","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"create, review, fix","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"FIX_TEXT","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"(empty)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Text from --fix \"...\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"REVIEW_FILE","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"(empty)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Path from --review-file","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MODEL","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"(empty)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Model override from --model","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MAX_TOKENS","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"32768","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"32768 (max), 16384 (optimal), 8192 (efficient)","type":"text"}]}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"STOP if FAILED","type":"text","marks":[{"type":"strong"}]},{"text":" -- check parse-args.sh.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.5: Detect Mode","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Condition","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Mode","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--fix","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag present","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"FIX","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--review","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag present","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"REVIEW","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Otherwise","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CREATE","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.7: Classify Intent (MODE=create only)","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Skip this step for REVIEW and FIX modes.","type":"text"}]}]},{"type":"paragraph","content":[{"text":"Analyze the user's prompt text (","type":"text"},{"text":"$ARGUMENTS","type":"text","marks":[{"type":"code_inline"}]},{"text":") and the input type to classify intent. ","type":"text"},{"text":"Opus classifies automatically -- no AskUserQuestion needed","type":"text","marks":[{"type":"strong"}]},{"text":" (exception: INPUT_TYPE=html with ambiguous signal -- ask).","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Intent","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Signals","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Default GLM instruction","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"reproduce","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Polished mockup, \"exact\", \"copy\", \"pixel-perfect\", no modification language","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Reproduce this design as working code. Match every visual detail exactly.\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"creative","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"sketch\", \"wireframe\", \"rough\", \"make it look professional\", \"polish\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"This is a rough sketch. Create a polished, professional UI based on this layout. Use modern design, clean typography, harmonious colors.\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"enhance","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"add a\", \"include\", \"put a ... on\", existing design + additions","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"This is an existing design. Enhance it: {user request}. Keep all existing content intact.\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"modify","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"change\", \"update\", \"make darker\", color/font/layout changes","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Modify this design: {user changes}. Keep everything else unchanged.\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"convert","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"to React\", \"to Flutter\", \"convert\", INPUT_TYPE=html + different framework","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Convert this {source} to {FRAMEWORK}. Preserve visual appearance.\"","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Default:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"reproduce","type":"text","marks":[{"type":"code_inline"}]},{"text":" (matches current behavior when no specific signals detected).","type":"text"}]},{"type":"paragraph","content":[{"text":"Store as variables for later use:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"INTENT","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- one of: reproduce, creative, enhance, modify, convert","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"GLM_INSTRUCTION","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- the instruction text (from table above, with placeholders filled from user prompt)","type":"text"}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Exception:","type":"text","marks":[{"type":"strong"}]},{"text":" If INPUT_TYPE=html and no clear intent signal in prompt -- ","type":"text"},{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"HTML input detected. What would you like to do?","type":"text"}]},{"type":"paragraph","content":[{"text":"Options:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Convert to {FRAMEWORK} (preserve appearance)\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Reproduce as clean HTML/CSS from scratch\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Use as reference -- create improved version\"","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Process Input by Type","type":"text"}]},{"type":"paragraph","content":[{"text":"Based on ","type":"text"},{"text":"INPUT_TYPE","type":"text","marks":[{"type":"code_inline"}]},{"text":" from parse-args.sh:","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"If INPUT_TYPE=image","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"IMAGE=\"IMAGE_PATH_HERE\"\n[ -f \"$IMAGE\" ] && file --mime-type \"$IMAGE\" | grep -qE ': image/' && echo \"VALID_IMAGE\" || echo \"INVALID\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If INVALID:","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"The file \"{IMAGE}\" is not a valid image. Please provide a valid input:","type":"text"}]},{"type":"paragraph","content":[{"text":"Options:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Enter path to screenshot file (PNG/JPG/WebP)\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Enter a URL to screenshot\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Enter a text description instead\"","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"On answer:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"File path -> re-validate as image, update IMAGE and INPUT_TYPE=image","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"URL -> update IMAGE, set INPUT_TYPE=url, go to URL processing above","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Text description -> update IMAGE with text, set INPUT_TYPE=text","type":"text"}]}]}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"If INPUT_TYPE=url","type":"text"}]},{"type":"paragraph","content":[{"text":"Take a Playwright screenshot of the URL first: ","type":"text"},{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"URL=\"URL_HERE\"\nnpx playwright screenshot --full-page \"$URL\" /tmp/d2c-url-screenshot.png 2>&1 && echo \"SCREENSHOT_OK\" || echo \"SCREENSHOT_FAILED\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If SCREENSHOT_OK:","type":"text","marks":[{"type":"strong"}]},{"text":" Set IMAGE=/tmp/d2c-url-screenshot.png and continue as image input. ","type":"text"},{"text":"If SCREENSHOT_FAILED:","type":"text","marks":[{"type":"strong"}]},{"text":" Try using Playwright MCP ","type":"text"},{"text":"browser_navigate","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"browser_take_screenshot","type":"text","marks":[{"type":"code_inline"}]},{"text":". If Playwright MCP also fails:","type":"text"}]}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Could not take screenshot of \"{URL}\". The URL may be unreachable or Playwright is not available. Choose alternative:","type":"text"}]},{"type":"paragraph","content":[{"text":"Options:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"I'll provide a screenshot file instead\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Convert from text description\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Skip -- I'll paste the HTML source\"","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"On answer:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Screenshot file -> ask for path, set INPUT_TYPE=image","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Text description -> ask for description, set INPUT_TYPE=text","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"HTML source -> ask for file path, set INPUT_TYPE=html","type":"text"}]}]}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"If INPUT_TYPE=html","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"HTML_FILE=\"HTML_PATH_HERE\"\n[ -f \"$HTML_FILE\" ] && echo \"HTML_VALID ($(wc -l \u003c \"$HTML_FILE\" | tr -d ' ') lines)\" || echo \"HTML_MISSING\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If HTML_VALID:","type":"text","marks":[{"type":"strong"}]},{"text":" Attempt to screenshot the HTML for dual input (image + HTML source):","type":"text"}]}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"HTML_FILE=\"HTML_PATH_HERE\"\nnpx playwright screenshot --full-page \"file://$(cd \"$(dirname \"$HTML_FILE\")\" && pwd)/$(basename \"$HTML_FILE\")\" /tmp/d2c-html-screenshot.png 2>&1 && echo \"SCREENSHOT_OK\" || echo \"SCREENSHOT_FAILED\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If SCREENSHOT_OK:","type":"text","marks":[{"type":"strong"}]},{"text":" Set ","type":"text"},{"text":"HTML_SCREENSHOT=/tmp/d2c-html-screenshot.png","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"DUAL_INPUT=true","type":"text","marks":[{"type":"code_inline"}]},{"text":". Will use ","type":"text"},{"text":"glm-build-request.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" with both screenshot and HTML source.","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If SCREENSHOT_FAILED:","type":"text","marks":[{"type":"strong"}]},{"text":" Try fallback:","type":"text"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"command -v wkhtmltoimage >/dev/null 2>&1 && wkhtmltoimage --quality 90 --width 1440 \"$HTML_FILE\" /tmp/d2c-html-screenshot.png 2>&1 && echo \"SCREENSHOT_OK\" || echo \"SCREENSHOT_FAILED\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If still FAILED:","type":"text","marks":[{"type":"strong"}]},{"text":" Try Playwright MCP ","type":"text"},{"text":"browser_navigate","type":"text","marks":[{"type":"code_inline"}]},{"text":" to ","type":"text"},{"text":"file://","type":"text","marks":[{"type":"code_inline"}]},{"text":" URL + ","type":"text"},{"text":"browser_take_screenshot","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If all fail:","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Could not screenshot the HTML file. Choose how to proceed:","type":"text"}]},{"type":"paragraph","content":[{"text":"Options:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"I'll provide a screenshot file\" (ask for path, set DUAL_INPUT=true)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Continue without screenshot (text-only)\" (set DUAL_INPUT=false)","type":"text"}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"When ","type":"text"},{"text":"DUAL_INPUT=false","type":"text","marks":[{"type":"code_inline"}]},{"text":": Will use ","type":"text"},{"text":"glm-build-text-request.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" (text-only with HTML content).","type":"text"}]}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"If INPUT_TYPE=text","type":"text"}]},{"type":"paragraph","content":[{"text":"The description text is in the IMAGE field. No validation needed -- will use glm-build-text-request.sh in Phase 2.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Confirm Settings (if no flags provided)","type":"text"}]},{"type":"paragraph","content":[{"text":"If IMAGE was the only argument (no flags), ","type":"text"},{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Design-to-Code Configuration:\n\nInput: {IMAGE} ({INPUT_TYPE})\nFramework: html (HTML/CSS), react (React 18 + CSS Modules), flutter (Flutter Web), custom\nProfile: max (pixel-perfect), optimal (balanced), efficient (fast)\nProvider: zai (Z.ai direct), openrouter (OpenRouter proxy)\nOutput: ./d2c-output\n\nAccept defaults or specify changes?","type":"text"}]},{"type":"paragraph","content":[{"text":"Options: \"Accept defaults\" | \"Change framework\" | \"Change profile\" | \"Change provider\" | \"Change output dir\"","type":"text"}]},{"type":"paragraph","content":[{"text":"On \"Accept defaults\":","type":"text","marks":[{"type":"strong"}]},{"text":" Continue to Phase 0.5.","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"LOOP:","type":"text","marks":[{"type":"strong"}]},{"text":" After any single change below, re-present the confirmation dialog with updated values so the user can change more settings or accept. Exit loop on \"Accept defaults\".","type":"text"}]}]},{"type":"paragraph","content":[{"text":"On \"Change framework\":","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Select target framework:","type":"text"}]},{"type":"paragraph","content":[{"text":"Options: \"HTML/CSS (static, no build)\" | \"React 18 + CSS Modules (Vite build)\" | \"Flutter Web (flutter build)\" | \"Custom (describe your stack)\"","type":"text"}]},{"type":"paragraph","content":[{"text":"On answer: update FRAMEWORK. If \"Custom\" -> ","type":"text"},{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" for stack description, write to ","type":"text"},{"text":"/tmp/d2c-custom-context.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"On \"Change profile\":","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Select quality profile:","type":"text"}]},{"type":"paragraph","content":[{"text":"Options: \"Maximum -- pixel-perfect, all details ($0.05-0.08)\" | \"Optimal -- good quality, balanced ($0.03-0.05)\" | \"Efficient -- fast, basic layout ($0.01-0.03)\"","type":"text"}]},{"type":"paragraph","content":[{"text":"On answer: update PROFILE and MAX_TOKENS accordingly.","type":"text"}]},{"type":"paragraph","content":[{"text":"On \"Change provider\":","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Select API provider:","type":"text"}]},{"type":"paragraph","content":[{"text":"Options: \"Z.ai (direct, system message caching, free tier)\" | \"OpenRouter (unified API, model routing)\"","type":"text"}]},{"type":"paragraph","content":[{"text":"On answer: update PROVIDER.","type":"text"}]},{"type":"paragraph","content":[{"text":"On \"Change output dir\":","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Enter output directory path:","type":"text"}]},{"type":"paragraph","content":[{"text":"On answer: update OUTPUT.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 0.5: API Key Setup (first-time only)","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Check API Key","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"[ -f .env ] && . .env\nPROVIDER=\"PROVIDER_HERE\"\nif [ \"$PROVIDER\" = \"zai\" ]; then\n [ -n \"$ZAI_API_KEY\" ] && echo \"KEY_SET\" || echo \"KEY_MISSING\"\nelif [ \"$PROVIDER\" = \"openrouter\" ]; then\n [ -n \"$OPENROUTER_API_KEY\" ] && echo \"KEY_SET\" || echo \"KEY_MISSING\"\nfi","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If KEY_SET","type":"text","marks":[{"type":"strong"}]},{"text":" — skip to Phase 1.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Ask Provider Choice (if KEY_MISSING)","type":"text"}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"API key required. Which provider do you have a key for?\n\n- Z.ai: Get key at https://z.ai -- direct GLM access, free tier available\n- OpenRouter: Get key at https://openrouter.ai -- unified API, many models","type":"text"}]},{"type":"paragraph","content":[{"text":"Options:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Z.ai (direct API)\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"OpenRouter (unified API)\"","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"On answer:","type":"text","marks":[{"type":"strong"}]},{"text":" Update PROVIDER based on choice (zai or openrouter).","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2.5: Ask for Key Value","type":"text"}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Paste your {PROVIDER_NAME} API key:","type":"text"}]},{"type":"paragraph","content":[{"text":"Options: (free text input)","type":"text"}]},{"type":"paragraph","content":[{"text":"On answer:","type":"text","marks":[{"type":"strong"}]},{"text":" Store the key value. Proceed to Step 3.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Validate Key (BEFORE saving)","type":"text"}]},{"type":"paragraph","content":[{"text":"Validate the key first to avoid persisting invalid credentials:","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"PROVIDER=\"PROVIDER_HERE\"\nKEY=\"KEY_VALUE_HERE\"\nif [ \"$PROVIDER\" = \"zai\" ]; then\n URL=\"https://api.z.ai/api/paas/v4/chat/completions\"\n MODEL=\"glm-4.6v-flash\"\nelse\n URL=\"https://openrouter.ai/api/v1/chat/completions\"\n MODEL=\"z-ai/glm-4.6v-flash\"\nfi\nHTTP=$(curl -s -w \"%{http_code}\" -o /tmp/d2c-key-test.json \\\n --max-time 10 \\\n -X POST \"$URL\" \\\n -H \"Authorization: Bearer $KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"{\\\"model\\\":\\\"$MODEL\\\",\\\"messages\\\":[{\\\"role\\\":\\\"user\\\",\\\"content\\\":\\\"test\\\"}],\\\"max_tokens\\\":5}\")\n[ \"$HTTP\" -ge 200 ] && [ \"$HTTP\" -lt 300 ] && echo \"KEY_VALID\" || echo \"KEY_INVALID (HTTP $HTTP)\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If KEY_VALID:","type":"text","marks":[{"type":"strong"}]},{"text":" Save key (Step 4) then continue.","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If KEY_INVALID (attempt 1 of 2):","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"API key validation failed (HTTP {CODE}). Common causes:\n- Key is expired or revoked\n- Wrong provider selected (Z.ai key used with OpenRouter or vice versa)\n- Key has no credits/quota\n\nPlease re-enter your API key or switch provider:","type":"text"}]},{"type":"paragraph","content":[{"text":"Options:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Re-enter key for same provider\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Switch to other provider\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Cancel -- I'll set the env var manually\"","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"On \"Re-enter key\":","type":"text","marks":[{"type":"strong"}]},{"text":" Go back to Step 2.5 with new key. ","type":"text"},{"text":"On \"Switch provider\":","type":"text","marks":[{"type":"strong"}]},{"text":" Toggle PROVIDER (zai\u003c->openrouter), go to Step 2. ","type":"text"},{"text":"On \"Cancel\":","type":"text","marks":[{"type":"strong"}]},{"text":" Output: \"Set ","type":"text"},{"text":"ZAI_API_KEY","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"OPENROUTER_API_KEY","type":"text","marks":[{"type":"code_inline"}]},{"text":" in your shell, then re-run the skill.\" ","type":"text"},{"text":"STOP.","type":"text","marks":[{"type":"strong"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If KEY_INVALID (attempt 2 of 2):","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"paragraph","content":[{"text":"Output: \"API key validation failed twice. Please verify your key at https://z.ai or https://openrouter.ai and set the environment variable manually: ","type":"text"},{"text":"export ZAI_API_KEY=your-key-here","type":"text","marks":[{"type":"code_inline"}]},{"text":" Then re-run: ","type":"text"},{"text":"/brewui:glm-design-to-code {original args}","type":"text","marks":[{"type":"code_inline"}]},{"text":"\" ","type":"text"},{"text":"STOP.","type":"text","marks":[{"type":"strong"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 4: Save Key to .env","type":"text"}]},{"type":"paragraph","content":[{"text":"Save the validated key so it persists across Bash calls:","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"PROVIDER=\"PROVIDER_HERE\"\nKEY=\"KEY_VALUE_HERE\"\nif [ \"$PROVIDER\" = \"zai\" ]; then\n VAR=\"ZAI_API_KEY\"\nelse\n VAR=\"OPENROUTER_API_KEY\"\nfi\necho \"export $VAR=\\\"$KEY\\\"\" > .env\ngrep -q '^\\.env

<instructions GLM Design-to-Code Converts design inputs (screenshots, text descriptions, HTML files, URLs) to working frontend code using GLM vision models. Three modes: CREATE, REVIEW, FIX. Arguments: Mode Routing | Mode | Flow | |------|------| | CREATE | Phase 0 → 0.5 → 1 → 2 → 3 (with auto-fix) → 4 (mandatory verify) → 5 (if --review) | | REVIEW | Phase 0 → 0.5 → 1 → 5 | | FIX | Phase 0 → 0.5 → 1 → 6 | PARAMETER PRIORITY: User prompt arguments ALWAYS override defaults and environment. 1. Explicit flags in ( , , , ) → highest priority 2. API keys from prompt text (if user pasted a key inli…

.gitignore 2>/dev/null || echo '.env' >> .gitignore\necho \"KEY_SAVED to .env ($VAR)\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 5: Choose Where to Save Key Permanently","type":"text"}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"API key validated. Where should it be saved permanently?\n\n- CLAUDE.local.md — Claude Code local config (not committed, Claude reads at startup)\n- ~/.zshrc — system-wide, available in all terminals and projects\n- .env — project-local dotenv file (gitignored, sourced by skill)","type":"text"}]},{"type":"paragraph","content":[{"text":"Options:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Save to CLAUDE.local.md (Claude Code standard, recommended)\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Save to ~/.zshrc (system-wide)\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Keep in .env only (already saved)\"","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"On \"CLAUDE.local.md\":","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"CLAUDE.local.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" is a standard Claude Code file in the project root — local instructions read by Claude at session start, not committed to git.","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":". .env\nPROVIDER=\"PROVIDER_HERE\"\nif [ \"$PROVIDER\" = \"zai\" ]; then\n VAR=\"ZAI_API_KEY\"\n VAL=\"$ZAI_API_KEY\"\nelse\n VAR=\"OPENROUTER_API_KEY\"\n VAL=\"$OPENROUTER_API_KEY\"\nfi\nif [ -f CLAUDE.local.md ]; then\n grep -q \"$VAR\" CLAUDE.local.md && echo \"Already in CLAUDE.local.md\" || printf '\\n## GLM API Key\\n\\nBefore running glm-design-to-code, set env var:\\n`export %s=%s`\\n' \"$VAR\" \"$VAL\" >> CLAUDE.local.md\nelse\n printf '# Local Config\\n\\n## GLM API Key\\n\\nBefore running glm-design-to-code, set env var:\\n`export %s=%s`\\n' \"$VAR\" \"$VAL\" > CLAUDE.local.md\nfi\necho \"Saved to CLAUDE.local.md\"","type":"text"}]},{"type":"paragraph","content":[{"text":"On \"~/.zshrc\":","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":". .env\nPROVIDER=\"PROVIDER_HERE\"\nif [ \"$PROVIDER\" = \"zai\" ]; then\n echo \"export ZAI_API_KEY=\\\"$ZAI_API_KEY\\\"\" >> ~/.zshrc\nelse\n echo \"export OPENROUTER_API_KEY=\\\"$OPENROUTER_API_KEY\\\"\" >> ~/.zshrc\nfi\necho \"Saved to ~/.zshrc (available in new terminal sessions)\"","type":"text"}]},{"type":"paragraph","content":[{"text":"On \".env only\":","type":"text","marks":[{"type":"strong"}]},{"text":" Already saved in Step 3. Done, continue to Phase 1.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 1: Validate Prerequisites","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Check Tools and API Keys","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"[ -f .env ] && . .env\nPROVIDER=\"PROVIDER_HERE\"\necho \"=== Tools ===\"\ncommand -v jq && echo \"jq OK\" || echo \"jq MISSING\"\ncommand -v curl && echo \"curl OK\" || echo \"curl MISSING\"\ncommand -v base64 && echo \"base64 OK\" || echo \"base64 MISSING\"\necho \"=== API Key ===\"\nif [ \"$PROVIDER\" = \"zai\" ]; then\n [ -n \"$ZAI_API_KEY\" ] && echo \"ZAI_API_KEY SET\" || echo \"ZAI_API_KEY MISSING\"\nelif [ \"$PROVIDER\" = \"openrouter\" ]; then\n [ -n \"$OPENROUTER_API_KEY\" ] && echo \"OPENROUTER_API_KEY SET\" || echo \"OPENROUTER_API_KEY MISSING\"\nfi\necho \"=== Framework Tools ===\"\ncommand -v node && echo \"node $(node -v)\" || echo \"node MISSING\"\ncommand -v npx && echo \"npx OK\" || echo \"npx MISSING\"\ncommand -v flutter && echo \"flutter OK\" || echo \"flutter MISSING (only needed for flutter framework)\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"STOP if jq, curl, or API key MISSING","type":"text","marks":[{"type":"strong"}]},{"text":" -- tell user what to install/set.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Resolve Scripts Path","type":"text"}]},{"type":"paragraph","content":[{"text":"All pipeline scripts are at ","type":"text"},{"text":"${CLAUDE_SKILL_DIR}/scripts/","type":"text","marks":[{"type":"code_inline"}]},{"text":". Verify they exist:","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"SD=\"${CLAUDE_SKILL_DIR}/scripts\"\nfor s in glm-build-request.sh glm-build-text-request.sh glm-request.sh glm-extract.sh glm-verify.sh; do\n [ -f \"$SD/$s\" ] && echo \"$s OK\" || echo \"$s MISSING\"\ndone","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"STOP if any MISSING","type":"text","marks":[{"type":"strong"}]},{"text":" -- re-install plugin.","type":"text"}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 2: Build and Send Request","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Select Prompt and Context Files","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Framework","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Prompt","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Context","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"html","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/profile-{PROFILE}.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"(none)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"react","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/profile-{PROFILE}.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/context-react.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"flutter","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/profile-{PROFILE}.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/context-flutter.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"custom","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/profile-{PROFILE}.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"User-provided or ","type":"text"},{"text":"references/context-template.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"Read the prompt file to confirm it exists:","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"PROMPT=\"${CLAUDE_SKILL_DIR}/references/profile-PROFILE_HERE.md\"\n[ -f \"$PROMPT\" ] && echo \"PROMPT OK: $PROMPT\" || echo \"PROMPT MISSING\"","type":"text"}]},{"type":"paragraph","content":[{"text":"For custom framework: ","type":"text"},{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" user to describe their stack. Write to ","type":"text"},{"text":"/tmp/d2c-custom-context.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" using ","type":"text"},{"text":"context-template.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" as template.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Resolve Model ID","type":"text"}]},{"type":"paragraph","content":[{"text":"If MODEL was set via ","type":"text","marks":[{"type":"strong"}]},{"text":"--model","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":":","type":"text","marks":[{"type":"strong"}]},{"text":" Use it directly, but ensure OpenRouter prefix:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If PROVIDER=openrouter and MODEL does not start with ","type":"text"},{"text":"z-ai/","type":"text","marks":[{"type":"code_inline"}]},{"text":" → prepend ","type":"text"},{"text":"z-ai/","type":"text","marks":[{"type":"code_inline"}]},{"text":" (e.g., ","type":"text"},{"text":"glm-4.6v","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"z-ai/glm-4.6v","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If PROVIDER=zai and MODEL starts with ","type":"text"},{"text":"z-ai/","type":"text","marks":[{"type":"code_inline"}]},{"text":" → strip the prefix (e.g., ","type":"text"},{"text":"z-ai/glm-5v-turbo","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"glm-5v-turbo","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"If MODEL is empty (no ","type":"text","marks":[{"type":"strong"}]},{"text":"--model","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" flag):","type":"text","marks":[{"type":"strong"}]},{"text":" Use defaults:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Provider","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Default Model ID","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"zai","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"glm-5v-turbo","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"openrouter","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"z-ai/glm-5v-turbo","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2.5: Display Resolved Configuration","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"MANDATORY","type":"text","marks":[{"type":"strong"}]},{"text":" — output before ANY API call in ALL modes. Shows user exactly what was resolved from their prompt, flags, env, and defaults. Mark overridden values with source.","type":"text"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"## Resolved Configuration\n\n| Setting | Value | Source |\n|---------|-------|--------|\n| Mode | `{MODE}` | {auto-detected / --review / --fix} |\n| Input | `{IMAGE}` ({INPUT_TYPE}) | {argument / prompt text} |\n| Framework | `{FRAMEWORK}` | {--framework / default: html} |\n| Profile | `{PROFILE}` (max_tokens={MAX_TOKENS}) | {--profile / default: max} |\n| Provider | `{PROVIDER}` | {--provider / default: zai} |\n| Model | `{MODEL}` | {--model / default for provider} |\n| Intent | `{INTENT}` | {auto-detected from prompt / default: reproduce} |\n| Instruction | `{first 80 chars of GLM_INSTRUCTION}...` | {formulated from intent + user prompt} |\n| Dual Input | `{yes/no}` | {HTML screenshotted / image only / text only} |\n| API Key | `{VAR_NAME}=***{last 4 chars}` | {prompt / .env / shell env} |\n| Output | `{OUTPUT}` | {--output / default: ./d2c-output} |\n\n**Expected result:** {description based on mode — e.g., \"HTML/CSS files in ./d2c-output\" or \"Review score with differences\" or \"Targeted fixes to existing code\"}","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Build Request Payload","type":"text"}]},{"type":"paragraph","content":[{"text":"Route to the correct script based on input type, dual input flag, and intent:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"INPUT_TYPE","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"DUAL_INPUT","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Script","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Extra args","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"image","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"N/A","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"glm-build-request.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"$GLM_INSTRUCTION\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"html","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"true","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"glm-build-request.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"$GLM_INSTRUCTION\" \"$HTML_FILE\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"html","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"false","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"glm-build-text-request.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"$GLM_INSTRUCTION\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"text","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"N/A","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"glm-build-text-request.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"$GLM_INSTRUCTION\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"url","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"N/A","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"glm-build-request.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"$GLM_INSTRUCTION\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"For INPUT_TYPE=image or url (or html with DUAL_INPUT=true):","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"SD=\"${CLAUDE_SKILL_DIR}/scripts\"\nPROMPT=\"${CLAUDE_SKILL_DIR}/references/profile-PROFILE_HERE.md\"\nCONTEXT=\"CONTEXT_PATH_OR_EMPTY\"\nIMAGE=\"IMAGE_PATH_HERE\"\nMODEL=\"MODEL_ID_HERE\"\nGLM_INSTRUCTION=\"INSTRUCTION_HERE\"\nHTML_SOURCE=\"HTML_FILE_OR_EMPTY\"\n\nbash \"$SD/glm-build-request.sh\" \"$IMAGE\" \"$PROMPT\" \"$CONTEXT\" \"$MODEL\" MAX_TOKENS_HERE 0.2 0.85 \"$GLM_INSTRUCTION\" \"$HTML_SOURCE\" > /tmp/d2c-payload.json && echo \"PAYLOAD OK ($(wc -c \u003c /tmp/d2c-payload.json | tr -d ' ') bytes)\" || echo \"PAYLOAD FAILED\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Replace all placeholders with actual values. For non-dual HTML or non-HTML input, leave HTML_SOURCE empty (\"\").","type":"text"}]},{"type":"paragraph","content":[{"text":"For INPUT_TYPE=html (DUAL_INPUT=false) or INPUT_TYPE=text:","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"SD=\"${CLAUDE_SKILL_DIR}/scripts\"\nPROMPT=\"${CLAUDE_SKILL_DIR}/references/profile-PROFILE_HERE.md\"\nCONTEXT=\"CONTEXT_PATH_OR_EMPTY\"\nINPUT=\"INPUT_VALUE_HERE\"\nMODEL=\"MODEL_ID_HERE\"\nGLM_INSTRUCTION=\"INSTRUCTION_HERE\"\n\nbash \"$SD/glm-build-text-request.sh\" \"$INPUT\" \"$PROMPT\" \"$CONTEXT\" \"$MODEL\" MAX_TOKENS_HERE 0.2 0.85 \"$GLM_INSTRUCTION\" > /tmp/d2c-payload.json && echo \"PAYLOAD OK ($(wc -c \u003c /tmp/d2c-payload.json | tr -d ' ') bytes)\" || echo \"PAYLOAD FAILED\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"For text input, INPUT is the description string. For HTML input, INPUT is the file path. Note: text-only requests can use non-vision models (glm-4.7-flash, glm-5-turbo) which may be cheaper.","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"STOP if FAILED","type":"text","marks":[{"type":"strong"}]},{"text":" -- check image path, prompt file.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 4: Send to API","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"[ -f .env ] && . .env\nSD=\"${CLAUDE_SKILL_DIR}/scripts\"\nbash \"$SD/glm-request.sh\" /tmp/d2c-payload.json /tmp/d2c-response.json PROVIDER_HERE && echo \"API OK\" || echo \"API FAILED\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"STOP if FAILED","type":"text","marks":[{"type":"strong"}]},{"text":" -- check API key, network, provider.","type":"text"}]}]},{"type":"paragraph","content":[{"text":"Check for truncation:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"FINISH=$(jq -r '.choices[0].finish_reason' /tmp/d2c-response.json)\n[ \"$FINISH\" = \"stop\" ] && echo \"COMPLETE\" || echo \"WARNING: finish_reason=$FINISH (may be truncated)\"","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 3: Extract and Build","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Extract and Validate Files","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"SD=\"${CLAUDE_SKILL_DIR}/scripts\"\nOUTPUT=\"OUTPUT_DIR_HERE\"\nmkdir -p \"$OUTPUT\"\nbash \"$SD/glm-extract.sh\" /tmp/d2c-response.json \"$OUTPUT\"\nEXIT_CODE=$?\necho \"EXIT_CODE=$EXIT_CODE\"\n[ $EXIT_CODE -eq 0 ] && echo \"EXTRACT OK\" || [ $EXIT_CODE -eq 1 ] && echo \"EXTRACT PARTIAL\" || echo \"EXTRACT FAILED\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Handle exit codes:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"0","type":"text","marks":[{"type":"code_inline"}]},{"text":" (OK) → continue to Step 2","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"1","type":"text","marks":[{"type":"code_inline"}]},{"text":" (partial) → Claude Code reads ","type":"text"},{"text":"/tmp/d2c-response.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" raw content using Read tool and manually extracts missing files using Write tool. Look for code blocks, ","type":"text"},{"text":"===FILE:","type":"text","marks":[{"type":"code_inline"}]},{"text":" markers, or inline code that the script missed","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"2","type":"text","marks":[{"type":"code_inline"}]},{"text":" (fail) → Claude Code reads ","type":"text"},{"text":"/tmp/d2c-response.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" and extracts ALL files manually","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Validate key files exist","type":"text","marks":[{"type":"strong"}]},{"text":" (framework-dependent):","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Framework","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Required file(s)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"React","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"src/main.jsx","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"src/App.jsx","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"package.json","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flutter","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"lib/main.dart","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"pubspec.yaml","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"HTML","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"index.html","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"If required files are missing → read ","type":"text"},{"text":"/tmp/d2c-response.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" with Read tool, find the code, write files with Write tool.","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"STOP only if response.json contains no usable code at all.","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: List Extracted Files","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"OUTPUT=\"OUTPUT_DIR_HERE\"\necho \"=== Extracted Files ===\"\nfind \"$OUTPUT\" -type f | head -50 | while read -r f; do\n echo \" $(echo \"$f\" | sed \"s|$OUTPUT/||\") ($(wc -l \u003c \"$f\" | tr -d ' ') lines)\"\ndone\necho \"=== Total ===\"\nfind \"$OUTPUT\" -type f | wc -l | tr -d ' '","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Build and Auto-Fix","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Step 3a: Build","type":"text"}]},{"type":"paragraph","content":[{"text":"Claude Code determines the framework from extracted files and builds the project:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Analyze file structure (package.json → Node/React, pubspec.yaml → Flutter, index.html without bundler deps → static HTML)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Install dependencies if needed","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run the appropriate build tool","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create any missing config files required for build","type":"text"}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Do NOT hardcode specific build commands — Claude Code knows how to build any stack. Analyze the actual project files and choose the right approach.","type":"text"}]}]},{"type":"paragraph","content":[{"text":"Build log → ","type":"text"},{"text":"/tmp/d2c-build-log.txt","type":"text","marks":[{"type":"code_inline"}]},{"text":". If build succeeds → go to Phase 4. If build fails → Step 3b.","type":"text"}]},{"type":"paragraph","content":[{"text":"HTML framework:","type":"text","marks":[{"type":"strong"}]},{"text":" No build step needed — skip directly to Phase 4.","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Step 3b: Auto-Fix (max 3 attempts)","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Claude Code fixes build errors directly — NO external API calls, NO GLM requests.","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"paragraph","content":[{"text":"Claude Code reads the build output, diagnoses compilation/build errors, and applies MINIMAL fixes.","type":"text"}]},{"type":"paragraph","content":[{"text":"RULES:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ONLY fix compilation/build errors","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Do NOT change design, colors, layout, fonts, spacing","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Do NOT refactor or rename anything","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Do NOT add functionality","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Each fix = smallest possible change","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Typical patterns","type":"text","marks":[{"type":"strong"}]},{"text":" (hints, NOT exhaustive — Claude Code diagnoses from actual errors):","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Missing import/dependency → add it","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Syntax error → fix syntax","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Unresolved reference → create stub or fix name","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Incompatible API → replace with compatible equivalent","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Missing config/entry file → create minimal version","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"After applying fixes: increment ATTEMPT counter. If ATTEMPT ≤ 3 → go back to Step 3a. If ATTEMPT > 3 → STOP, report full error log to user.","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Step 3c: Report Build Result","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"## Build Result\n\n| Metric | Value |\n|--------|-------|\n| Build attempts | {N} |\n| Fixes applied | {list of fixes} |\n| Final status | OK / FAILED |","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If FAILED after 3 attempts:","type":"text","marks":[{"type":"strong"}]},{"text":" Include full last build error log so user can diagnose manually.","type":"text"}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 4: Verify (Mandatory for CREATE mode)","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Required","type":"text","marks":[{"type":"strong"}]},{"text":" for CREATE mode. Skip only if Playwright is completely unavailable.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Serve and Screenshot","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"SD=\"${CLAUDE_SKILL_DIR}/scripts\"\nOUTPUT=\"OUTPUT_DIR_HERE\"\nbash \"$SD/glm-verify.sh\" \"$OUTPUT\" 8900","type":"text"}]},{"type":"paragraph","content":[{"text":"This outputs a URL. Take a screenshot with framework-appropriate timeout:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Framework","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Timeout","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reason","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"HTML","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"(none)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Static content, loads instantly","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"React","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--wait-for-timeout=3000","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Vite dev server + React hydration","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flutter","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--wait-for-timeout=8000","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flutter web engine initialization","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"FRAMEWORK=\"FRAMEWORK_HERE\"\nTIMEOUT_FLAG=\"\"\n[ \"$FRAMEWORK\" = \"react\" ] && TIMEOUT_FLAG=\"--wait-for-timeout=3000\"\n[ \"$FRAMEWORK\" = \"flutter\" ] && TIMEOUT_FLAG=\"--wait-for-timeout=8000\"\nnpx playwright screenshot --full-page $TIMEOUT_FLAG http://localhost:8900/ /tmp/d2c-result-screenshot.png 2>&1 && echo \"SCREENSHOT OK\" || echo \"SCREENSHOT FAILED\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If SCREENSHOT FAILED:","type":"text","marks":[{"type":"strong"}]},{"text":" Double the timeout and retry once:","type":"text"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"FRAMEWORK=\"FRAMEWORK_HERE\"\nTIMEOUT_FLAG=\"\"\n[ \"$FRAMEWORK\" = \"react\" ] && TIMEOUT_FLAG=\"--wait-for-timeout=6000\"\n[ \"$FRAMEWORK\" = \"flutter\" ] && TIMEOUT_FLAG=\"--wait-for-timeout=16000\"\n[ \"$FRAMEWORK\" = \"html\" ] && TIMEOUT_FLAG=\"--wait-for-timeout=3000\"\nnpx playwright screenshot --full-page $TIMEOUT_FLAG http://localhost:8900/ /tmp/d2c-result-screenshot.png 2>&1 && echo \"SCREENSHOT OK\" || echo \"SCREENSHOT FAILED\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"If still failed → skip screenshot, report URL for manual check.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Validate Screenshot Content","type":"text"}]},{"type":"paragraph","content":[{"text":"Read the screenshot using Read tool and verify it is not a blank/white page.","type":"text"}]},{"type":"paragraph","content":[{"text":"If blank page detected:","type":"text","marks":[{"type":"strong"}]},{"text":" Report to user: \"Build succeeded but page renders blank — possible runtime error. Check browser console at http://localhost:8900/\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Cleanup Server","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"bash \"${CLAUDE_SKILL_DIR}/scripts/glm-verify.sh\" --kill && echo \"SERVER STOPPED\"","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 5: Review (if --review flag or user requests)","type":"text"}]},{"type":"paragraph","content":[{"text":"Send both original design and generated screenshot to GLM for automated comparison.","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"ALWAYS","type":"text","marks":[{"type":"strong"}]},{"text":" output before sending:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"## Review Configuration\n| Setting | Value |\n|---------|-------|\n| Original | `{IMAGE}` |\n| Result | `{RESULT_IMAGE or /tmp/d2c-result-screenshot.png}` |\n| Provider | `{PROVIDER}` |\n| Model | `{MODEL}` |","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Build Review Request","type":"text"}]},{"type":"paragraph","content":[{"text":"The review requires sending TWO images. Build a custom payload:","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"SD=\"${CLAUDE_SKILL_DIR}/scripts\"\nREVIEW_PROMPT=\"${CLAUDE_SKILL_DIR}/references/review.md\"\nORIGINAL=\"IMAGE_PATH_HERE\"\nRESULT=\"${RESULT_IMAGE:-/tmp/d2c-result-screenshot.png}\"\nMODEL=\"MODEL_ID_HERE\"\n\n[ -f \"$ORIGINAL\" ] && [ -f \"$RESULT\" ] && [ -f \"$REVIEW_PROMPT\" ] && echo \"REVIEW INPUTS OK\" || echo \"REVIEW INPUTS MISSING\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Build review payload manually (two images in user message):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"REVIEW_PROMPT=\"${CLAUDE_SKILL_DIR}/references/review.md\"\nORIGINAL=\"IMAGE_PATH_HERE\"\nRESULT=\"${RESULT_IMAGE:-/tmp/d2c-result-screenshot.png}\"\nMODEL=\"MODEL_ID_HERE\"\n\nSYSTEM=$(cat \"$REVIEW_PROMPT\")\n\n# Base64 encode both images\nif base64 --help 2>&1 | grep -q '\\-w'; then\n B64_ORIG=$(base64 -w0 \"$ORIGINAL\")\n B64_RESULT=$(base64 -w0 \"$RESULT\")\nelse\n B64_ORIG=$(base64 -i \"$ORIGINAL\" | tr -d '\\n')\n B64_RESULT=$(base64 -i \"$RESULT\" | tr -d '\\n')\nfi\n\n# Detect MIME types\ncase \"$ORIGINAL\" in *.png) M1=\"image/png\";; *.jpg|*.jpeg) M1=\"image/jpeg\";; *) M1=\"image/png\";; esac\nM2=\"image/png\"\n\njq -n \\\n --arg model \"$MODEL\" \\\n --arg system \"$SYSTEM\" \\\n --arg uri1 \"data:${M1};base64,${B64_ORIG}\" \\\n --arg uri2 \"data:${M2};base64,${B64_RESULT}\" \\\n '{\n model: $model,\n temperature: 0.2,\n top_p: 0.85,\n max_tokens: 4096,\n messages: [\n { role: \"system\", content: $system },\n { role: \"user\", content: [\n { type: \"text\", text: \"Image 1 (original design):\" },\n { type: \"image_url\", image_url: { url: $uri1 } },\n { type: \"text\", text: \"Image 2 (generated code screenshot):\" },\n { type: \"image_url\", image_url: { url: $uri2 } }\n ]}\n ]\n }' > /tmp/d2c-review-payload.json && echo \"REVIEW PAYLOAD OK\" || echo \"REVIEW PAYLOAD FAILED\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Send Review","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"[ -f .env ] && . .env\nSD=\"${CLAUDE_SKILL_DIR}/scripts\"\nbash \"$SD/glm-request.sh\" /tmp/d2c-review-payload.json /tmp/d2c-review-response.json PROVIDER_HERE && echo \"REVIEW OK\" || echo \"REVIEW FAILED\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Extract Review","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"REVIEW=$(jq -r '.choices[0].message.content' /tmp/d2c-review-response.json)\necho \"$REVIEW\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Parse score from ","type":"text"},{"text":"score: N/10","type":"text","marks":[{"type":"code_inline"}]},{"text":" line in the review output.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 6: Fix Mode (if MODE=FIX)","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Skip Phases 2-5. Go directly here if MODE=FIX.","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"ALWAYS","type":"text","marks":[{"type":"strong"}]},{"text":" output before fixing:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"## Fix Configuration\n| Setting | Value |\n|---------|-------|\n| Mode | FIX |\n| Feedback source | {--fix \"text\" / --review-file path / previous review} |\n| Target directory | `{OUTPUT}` |\n| Expected result | Targeted edits to existing code files |","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Gather Fix Context","type":"text"}]},{"type":"paragraph","content":[{"text":"Read fix feedback from:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--fix \"text\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" argument → use text directly","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--fix --review-file path","type":"text","marks":[{"type":"code_inline"}]},{"text":" → read review JSON from file","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"No explicit feedback → look for ","type":"text"},{"text":"/tmp/d2c-review-response.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" from previous review","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Check for previous review\n[ -f \"/tmp/d2c-review-response.json\" ] && echo \"PREV_REVIEW EXISTS\" || echo \"NO_PREV_REVIEW\"","type":"text"}]},{"type":"paragraph","content":[{"text":"If no feedback source found:","type":"text"}]},{"type":"paragraph","content":[{"text":"ASK","type":"text","marks":[{"type":"strong"}]},{"text":" using AskUserQuestion:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"No review feedback found. What needs to be fixed in the generated code?\n\nDescribe specific issues, for example:\n- \"Sidebar is 240px, should be 280px\"\n- \"Header background is #2d2d2d, should be #1a1a2e\"\n- \"Missing syntax highlighting in code blocks\"\n- \"Footer section is completely missing\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Options:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Describe issues\" (free text)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Run automated review first\" (switches to REVIEW mode -> Phase 5)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"On \"Describe issues\":","type":"text","marks":[{"type":"strong"}]},{"text":" User provides free text feedback -> store as FIX_TEXT, continue to Step 2. ","type":"text"},{"text":"On \"Run automated review first\":","type":"text","marks":[{"type":"strong"}]},{"text":" Execute Phase 5 (Review), then return to Phase 6 with review feedback.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Read Existing Code","type":"text"}]},{"type":"paragraph","content":[{"text":"EXECUTE","type":"text","marks":[{"type":"strong"}]},{"text":" using Bash tool:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"OUTPUT=\"OUTPUT_DIR_HERE\"\necho \"=== Current Files ===\"\nfind \"$OUTPUT\" -type f -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.jsx' -o -name '*.dart' | head -20 | while read -r f; do\n echo \"--- $f ($(wc -l \u003c \"$f\" | tr -d ' ') lines) ---\"\ndone","type":"text"}]},{"type":"paragraph","content":[{"text":"Read each file using the Read tool.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Apply Fixes","type":"text"}]},{"type":"paragraph","content":[{"text":"Based on feedback, use the Edit tool to make targeted changes to the generated code files.","type":"text"}]},{"type":"paragraph","content":[{"text":"Common fixes:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Color corrections → update CSS custom properties","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Spacing/sizing → update CSS values","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Layout issues → restructure HTML/CSS","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Missing elements → add to relevant files","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 4: Re-verify (if Playwright available)","type":"text"}]},{"type":"paragraph","content":[{"text":"Follow Phase 4 steps to serve, screenshot, and compare.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 5: Report Changes","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"## Fix Applied\n\n| File | Changes |\n|------|---------|\n| `{file}` | `{description}` |\n\n## Verification\n- Screenshot: `{path or N/A}`\n- Previous score: `{N}/10`","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Error Handling","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Condition","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Action","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Image not found","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"AskUserQuestion for correct path","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"API key missing","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Set ","type":"text"},{"text":"ZAI_API_KEY","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"OPENROUTER_API_KEY","type":"text","marks":[{"type":"code_inline"}]},{"text":" env var.\" STOP","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"API returns error","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Show error, suggest retry or switch provider","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Response truncated","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Warn user, suggest ","type":"text"},{"text":"efficient","type":"text","marks":[{"type":"code_inline"}]},{"text":" profile for smaller output","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Build fails","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Auto-fix loop: Claude Code reads build errors, applies minimal compilation-only fixes (imports, syntax, references, config), retries build (max 3 attempts). Reports all fixes applied. If 3 attempts fail → show full error log to user","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Playwright not available","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skip screenshot, report URL for manual check","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Technical Notes","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Model:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"glm-5v-turbo","type":"text","marks":[{"type":"code_inline"}]},{"text":" (Z.ai) / ","type":"text"},{"text":"z-ai/glm-5v-turbo","type":"text","marks":[{"type":"code_inline"}]},{"text":" (OpenRouter)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Context window:","type":"text","marks":[{"type":"strong"}]},{"text":" 202K tokens","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Thinking mode:","type":"text","marks":[{"type":"strong"}]},{"text":" NOT supported on glm-5v-turbo -- never send thinking parameters","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"System message split:","type":"text","marks":[{"type":"strong"}]},{"text":" Prompt (profile) goes to system role, context + image go to user role","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"API params:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"temperature: 0.2","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"top_p: 0.85","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"max_tokens: MAX_TOKENS","type":"text","marks":[{"type":"code_inline"}]},{"text":" (profile-dependent: 32768/16384/8192)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"File markers:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"===FILE: path===","type":"text","marks":[{"type":"code_inline"}]},{"text":" ... ","type":"text"},{"text":"===END_FILE===","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Output Format","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"# GLM Design-to-Code\n\n## Configuration\n\n| Setting | Value |\n|---------|-------|\n| Screenshot | `{IMAGE}` |\n| Framework | `{FRAMEWORK}` |\n| Profile | `{PROFILE}` |\n| Provider | `{PROVIDER}` |\n| Model | `{MODEL_ID}` |\n| Output | `{OUTPUT}` |\n\n## API Response\n\n| Metric | Value |\n|--------|-------|\n| Finish reason | `{stop/length}` |\n| Input tokens | `{N}` |\n| Output tokens | `{N}` |\n\n## Extracted Files\n\n| File | Lines |\n|------|-------|\n| `{path}` | `{N}` |\n\n## Build\n\n| Step | Status |\n|------|--------|\n| Install | {OK/FAILED/N/A} |\n| Build | {OK/FAILED/N/A} |\n\n## Review (if requested)\n\n| Metric | Value |\n|--------|-------|\n| Score | `{N}/10` |\n| Summary | `{one-line}` |\n\n### Differences\n- {list}\n\n### Suggestions\n- {list}\n\n## Next Steps\n- {recommendations}","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"\u003c/instructions>","type":"text"}]}]},"metadata":{"date":"2026-06-05","name":"brewui:glm-design-to-code","model":"opus","author":"@skillopedia","source":{"stars":27,"repo_name":"claude-brewcode","origin_url":"https://github.com/kochetkov-ma/claude-brewcode/blob/HEAD/brewui/skills/glm-design-to-code/SKILL.md","repo_owner":"kochetkov-ma","body_sha256":"96f9642ddfce2cd9bd6544690d9912889002776f3b2a86869a614dc84f1c855d","cluster_key":"994df23e906a5e6fec520d16df032eaf4beef0c4851b2152feabde95c00b6058","clean_bundle":{"format":"clean-skill-bundle-v1","source":"kochetkov-ma/claude-brewcode/brewui/skills/glm-design-to-code/SKILL.md","attachments":[{"id":"2a2a5a7a-0ef3-5e62-9558-20078216284a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2a2a5a7a-0ef3-5e62-9558-20078216284a/attachment.md","path":"README.md","size":8317,"sha256":"25252ee9b5876347204e470e46efca918f4f657419ae495b6fa8c779ae670d14","contentType":"text/markdown; charset=utf-8"},{"id":"c3fc6579-87d2-5847-8cb7-886916bec813","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c3fc6579-87d2-5847-8cb7-886916bec813/attachment.md","path":"references/context-flutter.md","size":937,"sha256":"36c34b38be5ecbe5e11ed3ed0640f72534ae076e7dbe28779f7f5e7f18993603","contentType":"text/markdown; charset=utf-8"},{"id":"628f5add-2c4c-5187-b058-a78597afb9f2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/628f5add-2c4c-5187-b058-a78597afb9f2/attachment.md","path":"references/context-react.md","size":855,"sha256":"8b5105ad18bb315395591b7d74d941a1aa1cdc6aa390184c53a34952d8133a7e","contentType":"text/markdown; charset=utf-8"},{"id":"ca4c3a50-f5a1-5ca2-9930-bddbf487e7fd","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ca4c3a50-f5a1-5ca2-9930-bddbf487e7fd/attachment.md","path":"references/context-template.md","size":318,"sha256":"f135fa26b587fd2faf879db94c8dff27e2ba5442d27ede852db5c21ba79eb22d","contentType":"text/markdown; charset=utf-8"},{"id":"43ad7b77-a026-5523-8729-2f9bb92270d0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/43ad7b77-a026-5523-8729-2f9bb92270d0/attachment.md","path":"references/profile-efficient.md","size":616,"sha256":"c8c9d5b2543bbb3179dbc28bdc22ca94cf130a0eff684bb8f5ef5235c2ea3b92","contentType":"text/markdown; charset=utf-8"},{"id":"fd90c003-18a9-5ed7-8db6-186545dcca46","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fd90c003-18a9-5ed7-8db6-186545dcca46/attachment.md","path":"references/profile-max.md","size":1564,"sha256":"1b6536ce45b6c05e306c9d6bc667586c74f2a1ea7bed3aa82c79443b1aac4a2b","contentType":"text/markdown; charset=utf-8"},{"id":"406f815c-405f-5973-9a91-28b18150a8e6","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/406f815c-405f-5973-9a91-28b18150a8e6/attachment.md","path":"references/profile-optimal.md","size":898,"sha256":"06abeebb0b426b9791e8ee4c8d5234c026d228c96e19086e3b65b22fe4af47e8","contentType":"text/markdown; charset=utf-8"},{"id":"0333e6fb-60cd-5864-97cd-0cf82ab6d871","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0333e6fb-60cd-5864-97cd-0cf82ab6d871/attachment.md","path":"references/review.md","size":341,"sha256":"140615e9a46851b11b133b3ca4faaaceb3d75566fce4fb79772e0686624c2902","contentType":"text/markdown; charset=utf-8"},{"id":"93a75f1d-bf1e-558b-997d-70ba04a0601c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/93a75f1d-bf1e-558b-997d-70ba04a0601c/attachment.sh","path":"scripts/glm-build-request.sh","size":3753,"sha256":"c76eb4763e5abcce5b4030789bb67930248f50adb152c7d77e958125f8a33cd4","contentType":"application/x-sh; charset=utf-8"},{"id":"daec7422-67d3-5dd2-b74a-c7d386d4fd36","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/daec7422-67d3-5dd2-b74a-c7d386d4fd36/attachment.sh","path":"scripts/glm-build-text-request.sh","size":2131,"sha256":"173c57ccdef8f1b4780b970dea94a4ccea48e91ec3f63a97358494c337deac97","contentType":"application/x-sh; charset=utf-8"},{"id":"3faff76d-404e-568d-9c3c-4fed03ed6b5d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3faff76d-404e-568d-9c3c-4fed03ed6b5d/attachment.sh","path":"scripts/glm-extract.sh","size":4643,"sha256":"9cb08c51f3827de5badc83cbc9a2ec32c4aa35b1107df17d1de32910d9c88afc","contentType":"application/x-sh; charset=utf-8"},{"id":"5bd36b28-b24c-51fd-b056-b8276b8d875f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5bd36b28-b24c-51fd-b056-b8276b8d875f/attachment.sh","path":"scripts/glm-request.sh","size":2884,"sha256":"45a48ac085f545630baec0ff5cd16ffa4d986611a32238a6320c0d8ddfdd70d9","contentType":"application/x-sh; charset=utf-8"},{"id":"3bf70559-6e0d-5952-b186-e026b5699747","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3bf70559-6e0d-5952-b186-e026b5699747/attachment.sh","path":"scripts/glm-verify.sh","size":1702,"sha256":"b160e01966963a508d24606f289331b96fee42e7ee4a8049307a87306bce1cef","contentType":"application/x-sh; charset=utf-8"},{"id":"73386e84-a73a-511f-841e-ee2e6cb30dd0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/73386e84-a73a-511f-841e-ee2e6cb30dd0/attachment.sh","path":"scripts/parse-args.sh","size":3371,"sha256":"c36df51c1ab353c958090620b7b8aa67b110e95225cc34d3396be8b2924b5d1a","contentType":"application/x-sh; charset=utf-8"}],"bundle_sha256":"a2c44f4597688b7bc83ce8826b547825b30104916db68fd101b30e712171f39d","attachment_count":14,"text_attachments":8,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":6,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"brewui/skills/glm-design-to-code/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"browser-automation-scraping","category_label":"Browser"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"browser-automation-scraping","import_tag":"clean-skills-v1","description":"Generates frontend code from design screenshots, mockups, text descriptions, HTML files, or URLs using external GLM vision API. Modes: CREATE, REVIEW, FIX. Output: HTML, React, Flutter. Triggers: design to code, screenshot to code, mockup to code, d2c, generate frontend from image.","allowed-tools":["Read","Write","Edit","Glob","Grep","Bash","AskUserQuestion"],"argument-hint":"[input] [--framework html|react|flutter|custom] [--profile max|optimal|efficient] [--provider zai|openrouter] [--model MODEL_ID] [--output dir] [--review original.png result.png] [--fix 'feedback'] [--fix --review-file review.json]","user-invocable":true}},"renderedAt":1782980704534}

<instructions GLM Design-to-Code Converts design inputs (screenshots, text descriptions, HTML files, URLs) to working frontend code using GLM vision models. Three modes: CREATE, REVIEW, FIX. Arguments: Mode Routing | Mode | Flow | |------|------| | CREATE | Phase 0 → 0.5 → 1 → 2 → 3 (with auto-fix) → 4 (mandatory verify) → 5 (if --review) | | REVIEW | Phase 0 → 0.5 → 1 → 5 | | FIX | Phase 0 → 0.5 → 1 → 6 | PARAMETER PRIORITY: User prompt arguments ALWAYS override defaults and environment. 1. Explicit flags in ( , , , ) → highest priority 2. API keys from prompt text (if user pasted a key inli…