Autodesign
Build candidate UI(s) for a brief (loop.initial_candidates; default 1 = one UI, continuously refined), then iteratively improve u…
---
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 bestcombined≥ this.criteria— signal keys + weights forpipeline/benchmark.py.capture.viewport— viewport the html should target.models.*— which subagent uses which model tier.
- 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)