Blender model generated with the Python code output of Experiment 08 (left), and its physical model visualization (right). The input for generation was a 27-page PDF "The Segal Method", a special issue of The Architect's Journal from 1986.
CraftBot is an architect AI agent. It reads a design brief, grounds itself in domain knowledge by ingesting documents, images and other references, and outputs Python code that defines a building procedurally. Instead of producing meshes or images, CraftBot writes scripts that construct architectural geometry in Blender. From there it can produce the industry's standard representations: floorplans, sections, elevations, BIM models, bills of quantities. It can run in a fully automated loop of code generation, execution, visual feedback and revision. CraftBot is a research project asking whether large language models can take part in architectural design when they are constrained to work through executable CAD code.
This repo holds the code, iteration steps, references and outputs of the experiments so far, so anyone can build on CraftBot by pointing their own agent at it. Python and Blender were chosen for ease of access: both are open source, maintained, widely used, and free for commercial use.
A draft paper describing the project is in papers/:
CraftBot: An LLM Interlocutor in a Code-First Approach to Architectural Design (short paper, submitted to ICCC 2026)
Repository structure
papers/ Draft paper PDF
experiments/ 13 experiments, one folder each
manuals/ Timber construction manuals as extracted .md summaries, with INDEX.md (the PDFs themselves are gitignored)
skills/ Distilled modelling knowledge from the experiments, one skill per folder
tools/ Shared modelling kits and harness scripts (see tools/README.md)
viewer/ Web viewer: static site plus the exported models in viewer/models/
visuals/ Figures used in this README
outputs/ Default folder for headless renders (gitignored)
.claude/ Claude Code command /run-experiment, which starts an experiment run
.github/ GitHub Pages workflow that publishes viewer/ on every push to main
Each experiment folder follows the same layout:
input/holds everything given to the model: the prompt log (experiment_XX_prompts_chatgpt51.txt), reference images, and the shared Python geometry library (craftbot_lib.py) with an element placement template. Experiments 04, 08, 09, 11 and 13 also used a construction manual PDF; it was removed from the repository for copyright reasons, anoriginal_pdf_provenance.txtin the folder names it, and the extracted summary used during the run stays next to it.ChatGPT 5.1/holds the outputs per iteration: generated Python scripts (vXX.py) and Blender viewport screenshots of the resulting models.Fable/(ten experiments so far) holds the same per-iteration outputs from the Fable runs, plus the design rationale document, callouts file and archived conversation.references/(some experiments) holds additional reference and annotation images used during the iteration loop.
Experiments
The experiments started in November 2025 with ChatGPT 5.1 (runs through January 2026); other agents followed, with Fable runs added in August 2026, and the series is ongoing as of September 2026. Grouped by the type of reference material used:
Visual references. 01 Carport (king post truss), 02 Gothic Carport (hammer beam truss), 03 VIPP Shelter, 06 Prouvé 6x6 Demountable House
Hybrid references (images and text). 04 Construction Manual (prefabricated timber house), 05 Construction Manual Meta-Prompt, 07 Gehry Deconstruction, 08 The Segal Method, 09 How to CLT (ten-story building), 10 Staircase, 11 to 13 Hip Roof, Dormer Window and Roof Sheathing
Skills
skills/ holds knowledge distilled from the experiments: principles, methods and techniques extracted from the Fable design rationale documents and the reference documents, formatted as agent skills. Each skill is a folder with a SKILL.md whose frontmatter description says when to load it. They are written to be usable outside this repo. For Claude Code, place them in your .claude\skills\ folder, or add one line to CLAUDE.md telling the agent to check skills/ and load the relevant SKILL.md files before starting an experiment. The second method works with any agent.
| Skill | Load when |
|---|---|
| working-from-reference-documents | the experiment is grounded in a construction manual or guide |
| reading-visual-references | dimensions or topology must be read off photos, drawings or plans |
| procedural-geometry | writing Blender Python that generates construction geometry |
| non-orthogonal-geometry | sloped, tilted, twisted or warped surfaces are involved |
| verifying-models | setting up or running the render-inspect-revise loop |
| timber-framing | modelling framed timber structures or reviewing them as structures |
| roof-framing-and-sheathing | modelling pitched roofs, sheathing or coverings |
| modular-grids-and-panelization | prefabrication, panels, sheet materials, CLT, multi-storey systems |
| extending-previous-models | continuing or layering onto a previous experiment's model |
| writing-design-rationale | closing out a run, before archiving the transcript |
| running-craftbot-experiment | running a whole experiment in this repo, start to finish (repo-specific: folders, tools/, viewer export) |
The interpenetration check the skills refer to is tools/check_overlaps.py, the SAT test from the Fable render harnesses. It runs on any saved .blend.
Tools
tools/ is the code side of the same distillation: the geometry helpers the Fable runs converged on, extracted into importable modules so a new experiment starts from them instead of deriving them again. tools/README.md lists every module and function. In short:
| Module | What it gives an experiment script |
|---|---|
craftbot_lib.py (V 2.0) |
place_element as before, plus nested collections, box from corner coordinates, convex prisms |
geometry2d.py |
polygon clipping, member spacing, sheet tiling with holes, walls minus openings (pure Python, unit-tested) |
planes.py |
half-spaces, plane intersections, Roof planes, members built long and clipped (rafters, hips, braces, plates) |
ruled.py |
bilinear surfaces for warped and leaning walls and roofs |
framing.py |
stud walls with openings, cladding, decks, boards, solid walls with openings, roof layers, stairs |
sheathing.py |
mitred board sheathing on planar facets, hip dropping, protrusion check |
render_views.py |
headless renders with outlines, colours, hidden layers, close-ups and section cuts, plus the overlap check |
experiment_template.py |
starting point for a new experiment script |
Point your agent at both folders in its project instructions, one line each, as described under Skills above.
Headless execution
tools/run_experiment_headless.py executes an experiment script without opening the Blender GUI. It runs the script in background Blender, frames the generated geometry with an orthographic camera so the whole model is always visible, renders four orbit views with the Workbench engine (close to solid-mode viewport screenshots), and saves the resulting .blend file:
blender --background --python tools/run_experiment_headless.py -- <experiment.py> <lib_dir> [out_dir]
<experiment.py>is the path to the experiment script to execute.<lib_dir>is the folder containingcraftbot_lib.py(the experiment'sinput/folder).[out_dir]is an optional output folder forview_1..4.pngandmodel.blend; it defaults tooutputs/<experiment_name>/(gitignored).
Example (Windows):
"C:\Program Files\Blender Foundation\Blender 5.1\blender.exe" --background --python tools\run_experiment_headless.py -- "experiments\01_Carport_Assembly_Blender_Python\ChatGPT 5.1\experiment_01_chatgpt51_v01.py" "experiments\01_Carport_Assembly_Blender_Python\input"
Web viewer
CraftBot viewer interface: exp 06 Prouvé Cabanon (left, MONO 1 mode), exp 04 Construction Manual (middle, BLUEPRINT mode) and exp 07 Gehry Deconstruction (right, MONO 2 mode) with callouts linking to a design rationale document
A WebGL viewer for all generated models lives in viewer/ and deploys to GitHub Pages (live link).
Since .blend files are not stored in the repo, each experiment script is executed once in headless Blender and exported to a compact JSON model format in viewer/models/, typically 10 to 20 times smaller than the corresponding .blend. The viewer is a static site: vanilla ES modules with three.js from a pinned CDN, no build step.
Features:
- A model and agent picker with an iteration slider. The camera stays put when switching iterations and only the elements that changed animate in.
- Seven render styles: plaster, solid, random, mono, wireframe, blueprint and 1-bit dither. Mono, wireframe and dither each have a light and a dark mode; clicking random again re-rolls its palette. The shaded styles carry screen-space ambient occlusion and thin black outlines to match the Blender Workbench renders, glazing is drawn semi-transparent, and the GUI re-themes itself with the active style.
- GPU-driven entry animations: elements drop, rise or assemble in construction order or layer by layer.
- Eight layer toggles (frame, exterior and interior cladding, interior boards, roof, floors, foundations, fixtures) with an always-visible material takeoff (length, volume, weight).
- Section planes on three axes, and a Blender-style navigation cube with a 4-view mode in which the three fixed views share one wheel zoom.
- Hover and click element inspection: a name and layer tag at the cursor, picking that works through section cuts, and the element's true oriented length, width and thickness drawn in the active style.
- For Fable runs, the design rationale document in a panel under the view cube, with callouts on the model (tags with leader lines, authored per run in
experiment_NN_fable_callouts.json) that link groups of elements to passages of the document. Click a tag to jump to the passage; hover a heading to see its callouts. - On phones the GUI starts collapsed with one section open at a time.
Run locally:
python -m http.server -d viewer 8123
Re-export models after adding or changing experiment scripts (uses headless Blender):
python tools/export_all_models.py # everything
python tools/export_all_models.py --only 08 # one experiment / pattern
python tools/export_all_models.py --index-only # no Blender: index + rationale docs only
python tools/layers.py --audit # every element name family -> viewer layer
python tools/layers.py --bake # re-bake layers into viewer/models/*.json
python tools/callouts.py --check # validate the rationale callout files
python tools/callouts.py --names 04 # element name patterns, for authoring callouts
The index step also copies each experiments/<exp>/Fable/experiment_NN_fable_design_rationale.md to viewer/models/<exp>/fable_rationale.md so the viewer can show it. The exporter re-winds meshes to face outward (some generators emit inside-out prisms); the viewer applies the same fix when parsing older exports.
Deployment: pushes to main publish viewer/ via .github/workflows/pages.yml. One-time repo setting: Settings, Pages, Source: GitHub Actions.
Notes
- Original ChatGPT conversation logs are not yet included; they may be added later.
- This README will be updated as the research progresses.
About
The project author is Luka Piškorec, previously a lecturer at Aalto University and researcher at ETH Zürich. He is a co-founder of TEN Studio (Zürich and Belgrade) and {protocell:labs} (Helsinki), practices that work at the intersection of architecture, design, digital art and research.
The project is part of the art-ai-fact initiative funded by Aalto University in 2025-2026.

