SuperAPI AI Directory

glm-design-to-code-trial

Design & creation

View repository

Updated 10-15 23:47

About this skill

Plugin: kochetkov-ma/claude-brewcode | Skill: glm-design-to-code-trial

GLM Design-to-Code (Trial)

Converts design screenshots or text descriptions to HTML/CSS using GLM vision models (Z.ai). Trial version — CREATE mode, HTML output only.

Arguments: $ARGUMENTS

Step 0: Trial vs Full Version

Show this comparison to the user:

Feature Trial Full (brewcode)
Input Image, Text Image, Text, HTML, URL
Output HTML/CSS only HTML, React, Flutter, Custom
Modes CREATE only CREATE, REVIEW, FIX
Profiles optimal (fixed) max, optimal, efficient
Provider Z.ai only Z.ai, OpenRouter
Scripts Inline (no deps) External scripts
Auto-review No Yes (--review flag)
Intent detection No Yes (5 intents)

Then ask the user:

USE AskUserQuestion tool:

This is the TRIAL version of glm-design-to-code.

1) Continue with trial (HTML output, CREATE mode)
2) Install full brewcode plugin (React, Flutter, review/fix modes, 5 intents)

Reply 1 or 2.

If user picks 2 -> show install commands and STOP:

claude plugin marketplace add https://github.com/kochetkov-ma/claude-brewcode
claude plugin install brewcode@claude-brewcode

Explain: full version supports React/Flutter/Custom output, CREATE/REVIEW/FIX modes, 5 intent types (reproduce, creative, enhance, modify, convert), OpenRouter provider, profile selection, and auto-review. Then STOP — do not proceed further.

If user picks 1 -> proceed to Step 1.

Step 1: API Key Setup

Check for ZAI_API_KEY in .env file first, then environment.

EXECUTE using Bash tool:

ZAI_API_KEY=""
if [ -f .env ]; then
  ZAI_API_KEY=$(grep -E '^ZAI_API_KEY=' .env 2>/dev/null | head -1 | cut -d'=' -f2- | tr -d '"' | tr -d "'")
fi
[ -z "$ZAI_API_KEY" ] && ZAI_API_KEY="${ZAI_API_KEY:-}"
if [ -n "$ZAI_API_KEY" ]; then
  echo "KEY_FOUND:${ZAI_API_KEY: -4}"
else
  echo "KEY_MISSING"
fi

If KEY_MISSING -> USE AskUserQuestion tool:

Z.ai API key not found.

Get a free key at https://open.z.ai (GLM models, free tier available).
Paste your API key:

Store the key in ZAI_API_KEY variable for subsequent steps.

Then validate with a lightweight curl:

EXECUTE using Bash tool:

HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "https://api.z.ai/api/paas/v4/models" \
  -H "Authorization: Bearer $ZAI_API_KEY" --max-time 10)
if [ "$HTTP_CODE" = "200" ]; then
  echo "KEY_VALID"
else
  echo "KEY_INVALID:$HTTP_CODE"
fi

STOP if KEY_INVALID — show error message with HTTP code and advise user to check the key at https://open.z.ai.

Save to .env and ensure .gitignore covers it:

EXECUTE using Bash tool:

if [ -f .env ]; then
  if grep -q '^ZAI_API_KEY=' .env; then
    sed -i.bak "s|^ZAI_API_KEY=.*|ZAI_API_KEY=$ZAI_API_KEY|" .env && rm -f .env.bak
  else
    echo "ZAI_API_KEY=$ZAI_API_KEY" >> .env
  fi
else
  echo "ZAI_API_KEY=$ZAI_API_KEY" > .env
fi
grep -qxF '.env' .gitignore 2>/dev/null || echo '.env' >> .gitignore
echo "Key saved (****${ZAI_API_KEY: -4})"

Step 2: Detect Input

Parse $ARGUMENTS to find input:

Pattern Type
Ends with .png, .jpg, .jpeg, .webp, .gif Image file
Everything else non-empty Text description
Empty / no input Ask user

For image files — validate existence with file --mime-type.

If no input found -> USE AskUserQuestion tool:

No input detected. Provide either:
- Path to a design screenshot (PNG, JPG, WebP, GIF)
- Text description of the desired design

Your input:

Store the detected input type (IMAGE or TEXT) and value for the next step.

Step 3: Build Request Payload

For IMAGE input

EXECUTE using Bash tool (replace IMAGE_PATH_VALUE with the actual resolved image path, and inject ZAI_API_KEY value):

set -e
IMAGE_PATH="IMAGE_PATH_VALUE"

command -v jq >/dev/null 2>&1 || { echo "jq is required. Install: brew install jq"; exit 1; }
command -v base64 >/dev/null 2>&1 || { echo "base64 is required"; exit 1; }

case "$IMAGE_PATH" in
  *.png)  MIME="image/png" ;;
  *.jpg|*.jpeg) MIME="image/jpeg" ;;
  *.webp) MIME="image/webp" ;;
  *.gif)  MIME="image/gif" ;;
  *) echo "Unsupported image format"; exit 1 ;;
esac

B64=$(base64 < "$IMAGE_PATH" | tr -d '\n')
DATA_URI="data:${MIME};base64,${B64}"

TMPURI=$(mktemp)
TMPUSER=$(mktemp)
TMPSYS=$(mktemp)
trap "rm -f '$TMPURI' '$TMPUSER' '$TMPSYS'" EXIT

printf '%s' "$DATA_URI" > "$TMPURI"
printf '%s' "Convert this design screenshot to working HTML/CSS code files." > "$TMPUSER"
cat > "$TMPSYS" <<'SYSPROMPT'
You are a skilled frontend developer. Follow the task instruction and produce clean, accurate code.

## Output format

Wrap every file in markers. Output markers and file content only — no text before, between, or after.

===FILE: path/to/file.ext===
content
===END_FILE===

Wrong (adds backticks): ```html\n===FILE: index.html===
Correct: ===FILE: index.html===

## Requirements

- Match design: correct colors, proportions, typography, layout structure
- CSS custom properties for colors
- Semantic HTML5, entry point: index.html
- CSS in separate .css file(s) — inline styles excluded
- JS in separate .js file(s) if needed
- CDN dependencies excluded unless specified in project context
- All text content from screenshot preserved verbatim
- Layout structure and proportions matched (sidebar, header, content areas)

Output starts with ===FILE: and ends with ===END_FILE===. Nothing else.
SYSPROMPT

jq -n \
  --rawfile system "$TMPSYS" \
  --rawfile user_text "$TMPUSER" \
  --rawfile data_uri "$TMPURI" \
  '{
    model: "glm-5v-turbo",
    temperature: 0.2,
    top_p: 0.85,
    max_tokens: 16384,
    messages: [
      { role: "system", content: ($system | rtrimstr("\n")) },
      { role: "user", content: [
        { type: "text", text: ($user_text | rtrimstr("\n")) },
        { type: "image_url", image_url: { url: ($data_uri | rtrimstr("\n")) } }
      ]}
    ]
  }' > /tmp/d2c-trial-payload.json

echo "Payload: /tmp/d2c-trial-payload.json ($(wc -c < /tmp/d2c-trial-payload.json | tr -d ' ') bytes)"

For TEXT input

EXECUTE using Bash tool (replace USER_TEXT_VALUE with the actual text description):

set -e
USER_TEXT="USER_TEXT_VALUE"

command -v jq >/dev/null 2>&1 || { echo "jq is required. Install: brew install jq"; exit 1; }

TMPUSER=$(mktemp)
TMPSYS=$(mktemp)
trap "rm -f '$TMPUSER' '$TMPSYS'" EXIT

printf '%s' "Create working frontend code files based on this description:

$USER_TEXT" > "$TMPUSER"
cat > "$TMPSYS" <<'SYSPROMPT'
You are a skilled frontend developer. Follow the task instruction and produce clean, accurate code.

## Output format

Wrap every file in markers. Output markers and file content only — no text before, between, or after.

===FILE: path/to/file.ext===
content
===END_FILE===

Wrong (adds backticks): ```html\n===FILE: index.html===
Correct: ===FILE: index.html===

## Requirements

- Match design: correct colors, proportions, typography, layout structure
- CSS custom properties for colors
- Semantic HTML5, entry point: index.html
- CSS in separate .css file(s) — inline styles excluded
- JS in separate .js file(s) if needed
- CDN dependencies excluded unless specified in project context
- All text content from screenshot preserved verbatim
- Layout structure and proportions matched (sidebar, header, content areas)

Output starts with ===FILE: and ends with ===END_FILE===. Nothing else.
SYSPROMPT

jq -n \
  --rawfile system "$TMPSYS" \
  --rawfile user_text "$TMPUSER" \
  '{
    model: "glm-5v-turbo",
    temperature: 0.2,
    top_p: 0.85,
    max_tokens: 16384,
    messages: [
      { role: "system", content: ($system | rtrimstr("\n")) },
      { role: "user", content: ($user_text | rtrimstr("\n")) }
    ]
  }' > /tmp/d2c-trial-payload.json

echo "Payload: /tmp/d2c-trial-payload.json ($(wc -c < /tmp/d2c-trial-payload.json | tr -d ' ') bytes)"

Step 4: Send to Z.ai API

EXECUTE using Bash tool (replace ZAI_API_KEY_VALUE with the actual key):

set -e
ZAI_API_KEY="ZAI_API_KEY_VALUE"

RESPONSE=$(curl -s -w "\n%{http_code}" \
  --max-time 300 \
  "https://api.z.ai/api/paas/v4/chat/completions" \
  -H "Authorization: Bearer $ZAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d @/tmp/d2c-trial-payload.json)

HTTP_CODE=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')

if [ "$HTTP_CODE" != "200" ]; then
  echo "API error (HTTP $HTTP_CODE): $BODY"
  exit 1
fi

echo "$BODY" > /tmp/d2c-trial-response.json

FINISH=$(jq -r '.choices[0].finish_reason // "unknown"' /tmp/d2c-trial-response.json)
TOKENS_IN=$(jq -r '.usage.prompt_tokens // "?"' /tmp/d2c-trial-response.json)
TOKENS_OUT=$(jq -r '.usage.completion_tokens // "?"' /tmp/d2c-trial-response.json)

echo "Response saved: /tmp/d2c-trial-response.json"
echo "  finish_reason: $FINISH | tokens: $TOKENS_IN in / $TOKENS_OUT out"

if [ "$FINISH" = "length" ]; then
  echo "WARNING: Response truncated (hit max_tokens)"
fi

STOP if API error — show the HTTP code and response body to the user.

Step 5: Extract Files

EXECUTE using Bash tool (replace OUTPUT_DIR_VALUE with ./d2c-output or user-specified directory):

set -e
OUTPUT_DIR="OUTPUT_DIR_VALUE"

CONTENT=$(jq -r '.choices[0].message.content // empty' /tmp/d2c-trial-response.json)

if [ -z "$CONTENT" ]; then
  echo "No content in response"
  exit 2
fi

mkdir -p "$OUTPUT_DIR"
EXIT_CODE=0

if printf '%s\n' "$CONTENT" | grep -q '===FILE:'; then
  EXPECTED=$(printf '%s\n' "$CONTENT" | grep -c '===FILE:' || true)
  echo "Expected files from markers: $EXPECTED" >&2

  TMPFILE=$(mktemp)
  trap "rm -f '$TMPFILE'" EXIT
  jq -r '.choices[0].message.content' /tmp/d2c-trial-response.json > "$TMPFILE"

  awk -v outdir="$OUTPUT_DIR" '
  /^===FILE: / {
    fname = $0
    sub(/^===FILE: */, "", fname)
    sub(/ *===.*$/, "", fname)
    sub(/=+$/, "", fname)
    gsub(/[^a-zA-Z0-9._\/\-]/, "", fname)
    gsub(/^\/+/, "", fname)
    if (fname ~ /\.\./) { next }
    if (fname == "") {
      skipped++
      print "WARNING: Skipped file with empty name after sanitization" > "/dev/stderr"
      next
    }
    current_file = outdir "/" fname
    current_fname = fname
    writing = 1
    next
  }
  /^===END_FILE===/ {
    if (writing && current_file != "") {
      close(current_file)
      file_count++
      print "  " current_fname " (" lines " lines)" > "/dev/stderr"
      lines = 0
    }
    writing = 0
    next
  }
  writing {
    if (lines == 0) {
      dir = current_file
      sub(/\/[^\/]*$/, "", dir)
      gsub(/\x27/,"\x27\\\x27\x27", dir)
      cmd = "mkdir -p \x27" dir "\x27"
      system(cmd)
      close(cmd)
      printf "" > current_file
      close(current_file)
    }
    print >> current_file
    lines++
  }
  END {
    if (writing && current_file != "") {
      close(current_file)
      file_count++
      print "WARNING: Truncated file (no ===END_FILE===): " current_fname > "/dev/stderr"
    }
    print "Extracted " file_count+0 " file(s)" > "/dev/stderr"
    if (skipped > 0) {
      print "Skipped " skipped " file(s) with invalid names" > "/dev/stderr"
    }
  }
  ' "$TMPFILE"

  rm -f "$TMPFILE"
  trap - EXIT

  # Post-extraction validation
  ACTUAL=$(find "$OUTPUT_DIR" -type f 2>/dev/null | wc -l | tr -d ' ')

  echo "" >&2
  echo "--- Extraction Validation ---" >&2
  echo "Expected: $EXPECTED file(s)" >&2
  echo "Extracted: $ACTUAL file(s)" >&2

  if [ "$ACTUAL" -eq 0 ]; then
    echo "ERROR: Total extraction failure" >&2
    EXIT_CODE=2
  elif [ "$ACTUAL" -lt "$EXPECTED" ]; then
    echo "WARNING: Partial extraction — $ACTUAL of $EXPECTED files" >&2
    EXIT_CODE=1
  fi

  # Check for empty files
  EMPTY_COUNT=0
  for file in $(find "$OUTPUT_DIR" -type f 2>/dev/null); do
    if [ ! -s "$file" ]; then
      EMPTY_COUNT=$((EMPTY_COUNT + 1))
      echo "  EMPTY: $(echo "$file" | sed "s|^$OUTPUT_DIR/||")" >&2
    fi
  done
  if [ "$EMPTY_COUNT" -gt 0 ]; then
    echo "WARNING: $EMPTY_COUNT empty file(s) detected" >&2
    [ "$EXIT_CODE" -eq 0 ] && EXIT_CODE=1
  fi

  # Verify index.html exists (HTML output)
  if [ ! -f "$OUTPUT_DIR/index.html" ]; then
    echo "WARNING: index.html not found in extracted files" >&2
    [ "$EXIT_CODE" -eq 0 ] && EXIT_CODE=1
  fi
else
  echo "No ===FILE: markers found. Trying code block extraction..." >&2

  printf '%s\n' "$CONTENT" | awk -v outdir="$OUTPUT_DIR" '
  BEGIN {
    map["html"] = "index.html"
    map["htm"] = "index.html"
    map["css"] = "styles.css"
    map["js"] = "script.js"
    map["javascript"] = "script.js"
    map[""] = "index.html"
  }
  /^```[a-zA-Z]/ {
    lang = $0
    sub(/^```/, "", lang)
    sub(/[^a-zA-Z0-9].*/, "", lang)
    lang = tolower(lang)
    in_block = 1
    content = ""
    next
  }
  /^```$/ && in_block {
    in_block = 0
    if (content != "") {
      base = map[lang]
      if (base == "") base = "file." lang
      if (seen[base]++) {
        ext_pos = index(base, ".")
        if (ext_pos > 0) {
          name_part = substr(base, 1, ext_pos - 1)
          ext_part = substr(base, ext_pos)
          base = name_part seen[base] ext_part
        } else {
          base = base seen[base]
        }
      }
      fname = outdir "/" base
      printf "%s", content > fname
      close(fname)
      lines_count = split(content, arr, "\n") - 1
      print "  " base " (" lines_count " lines)" > "/dev/stderr"
      file_count++
    }
    next
  }
  in_block {
    content = content $0 "\n"
  }
  END {
    if (file_count > 0) {
      print "Extracted " file_count " file(s) from code blocks" > "/dev/stderr"
    }
  }
  '

  EXTRACTED=$(find "$OUTPUT_DIR" -type f 2>/dev/null | wc -l | tr -d ' ')
  if [ "$EXTRACTED" -eq 0 ]; then
    echo "No code blocks found. Saving raw content as index.html" >&2
    printf '%s\n' "$CONTENT" > "$OUTPUT_DIR/index.html"
    echo "  index.html ($(printf '%s\n' "$CONTENT" | wc -l | tr -d ' ') lines)" >&2
  fi
fi

echo ""
echo "Output directory: $OUTPUT_DIR"
ls -la "$OUTPUT_DIR"

if [ "$EXIT_CODE" -eq 1 ]; then
  echo "WARNING: Partial extraction — review files above" >&2
elif [ "$EXIT_CODE" -eq 2 ]; then
  echo "ERROR: Extraction failed" >&2
fi
exit $EXIT_CODE

If exit code 1 (partial extraction): Re-read response content manually. Check if ===FILE: markers are present but malformed. Attempt targeted extraction of missing files by reading the response and using Write tool directly.

If exit code 2 (total failure): Show error to user. The API response may be malformed or empty. Check /tmp/d2c-trial-response.json content.

Step 6: Report + Promo Footer

Output a summary report to the user:

Config

Parameter Value
Model glm-5v-turbo
Max tokens 16384
Profile optimal (fixed)
Input type (IMAGE or TEXT)
Temperature 0.2
Top-p 0.85

API Stats

Metric Value
Tokens in (from response)
Tokens out (from response)
Finish reason (from response)

Extracted Files

List each file with line count from Step 5 output.

Output

Output directory: ./d2c-output

Then show the promo footer:

---

Want more? Full version supports React, Flutter, review/fix modes, 5 intents, OpenRouter provider.

Install brewcode:
  claude plugin marketplace add https://github.com/kochetkov-ma/claude-brewcode
  claude plugin install brewcode@claude-brewcode

Then use: /brewcode:glm-design-to-code