Autodesign

Build candidate UI(s) for a brief (loop.initial_candidates; default 1 = one UI, continuously refined), then iteratively improve u…

MaromSv 14 updated 1mo ago
Claude CodeGeneric
View source ↗
---
description: Build candidate UI(s) for a brief (loop.initial_candidates; default 1 = one UI, continuously refined), then iteratively improve under .autodesign/runs/<id>/
argument-hint: <brief — what UI to build>
---

You are running the **AutoDesign** loop on this brief:

> $ARGUMENTS

If `$ARGUMENTS` is empty, ask the user for a brief in one sentence, then proceed.

The architecture is in [CLAUDE.md](../../CLAUDE.md). The control surface is
[autodesign.md](../../autodesign.md) — read its yaml block before doing anything.

## The shape of the loop

brief --> [gen-0: build loop.initial_candidates UI(s)] --> score --> pick winner | v [gen-N>=1: refine the winner] <-- critique | v score --> new winner --> loop until threshold | v final.html + design_journey.html


Gen-0 builds `loop.initial_candidates` candidate(s). The default is **1**: build a
single UI and then continuously refine that one page every generation (no gen-0
fan-out — the lone candidate is trivially the winner). Set `initial_candidates > 1`
to fan out into several distinct starting directions and pick the best. Every
generation after gen-0 is a single critique-driven refinement of the previous
winner. The dashboard reads `.autodesign/runs/<id>/` to render the run.

## Setup

> **CRITICAL — always use the project venv.** The scoring signals live ONLY in
> `.venv` (`anthropic` for `vlm_judge`, `deepgaze_pytorch` for `saliency`). Bare
> `python` resolves to a different interpreter (e.g. miniconda) that lacks them,
> so every signal silently skips and **every score comes back `null`** — the
> dashboard then shows no scores. Run every command below as `.venv/bin/python …`
> (shell state does not persist between calls, so `source .venv/bin/activate`
> will NOT carry over — you must prefix each command explicitly).

1. **Load config + create the run dir.** Run from the repo root:

   ```bash
   .venv/bin/python -c "
   import json
   from pipeline.config import load_config
   from pipeline.artifacts import new_run_id, run_dir
   cfg = load_config()
   rid = new_run_id()
   d = run_dir(rid); d.mkdir(parents=True, exist_ok=True)
   print(json.dumps({'run_id': rid, 'run_dir': str(d), 'config': cfg}, indent=2))
   "

From the printed JSON extract: run_id, run_dir, and from config:

  • loop.initial_candidates — how many candidates for gen-0 (default 1).
  • loop.iterations — how many refinement generations after gen-0.
  • loop.target_score — stop early when best combined ≥ this.
  • criteria — signal keys + weights for pipeline/benchmark.py.
  • capture.viewport — viewport the html should target.
  • models.* — which subagent uses which model tier.
  1. Persist the brief to <run_dir>/brief.txt.

Generation 0 — minimal baseline (or fan out)

Generate loop.initial_candidates (default 1) candidate(s). With the default of 1, build a single minimal baseline (cand-00): a clean, correct page that delivers exactly what the brief asks and nothing more — NO creative flourishes, signature art direction, or heavy animation yet. The VLM judge then says what it lacks and the refinement rounds add the design on top. (The generator subagent enforces this — just let it build the plain baseline; don't ask for pizazz at gen-0.) When initial_candidates > 1, make the variants meaningfully different on at least three axes:

  • Layout (asymmetric left-hero / symmetric bold / editorial columns / illustration-led / minimal grid)
  • Primary focal element (typography hero / product preview / illustration / data)
  • Color & tone (light editorial / dark bold / neutral conversion / accent-color minimal)
  • Information density (sparse hero / dense product / mixed)

For each i in 0..loop.initial_candidates - 1:

a. Create the candidate dir.

.venv/bin/python -c "
from pipeline.artifacts import ensure_cand_dir
print(ensure_cand_dir('<run_id>', 0, <i>))
"

b. Generate the html. Invoke the generator subagent (Agent tool with subagent_type: generator). Pass it the brief, the viewport from config.capture.viewport, and a one-line hypothesis describing the design axis this sibling explores (e.g. "asymmetric left-hero, dark, sparse"). It MUST write a single self-contained html file at:

<run_dir>/gen-000/cand-NN/index.html

Inline all CSS. No external assets beyond Google Fonts. Viewport-ready for the configured size (default 1280×800). The generator MAY embed the hypothesis as an html comment at the top of the file.

When generating more than one candidate, spawn the generator calls in parallel (one message, multiple Agent tool calls) — they are independent. With the default of 1, this is just a single generator call.

c. Capture frames for each candidate:

.venv/bin/python -c "
from pathlib import Path
from pipeline.capture import capture
from pipeline.config import load_config
cfg = load_config()
out = Path('<run_dir>/gen-000/cand-NN')
capture(
    html_path=out / 'index.html',
    out_dir=out,
    viewport=tuple(cfg['capture']['viewport']),
    animation_seconds=float(cfg['capture']['animation_seconds']),
    keyframes=cfg['capture']['keyframes'],
)
"

pipeline/capture.py is implemented (Playwright): it writes the keyframe PNGs to <cand>/frames/ using config.capture (viewport, animation_seconds, keyframes). It skips gracefully if Playwright/chromium isn't installed (pip install playwright && playwright install chromium).

d. Score each candidate:

.venv/bin/python -m pipeline.benchmark --candidate <run_dir>/gen-000/cand-NN \
    --references --run-dir

Maintain Autodesign?

Let people know it's listed here — add the badge (live metrics, light/dark aware) or a plain link to your README or docs.

[Autodesign on getagentictools](https://getagentictools.com/loops/maromsv-autodesign?ref=badge)