Writing CAD as Code and Letting the Machine Check It

Writing 3D-printable shapes as code has one property no other design method has: the design is text. Text can be written by a machine and read by a machine. You can diff it and you can keep its history. When the subject is having AI design something, this format is the natural fit.
That much has been said for a while. What you hit in practice is a wall: nothing moves unless a person is watching. You run the generated code yourself, look at the shape, measure it, and ask for a correction. As long as a person brokers that round trip, the only thing that got faster is writing a line, and the whole process is still paced by the number of human turns.
Automating code CAD ought to mean removing that brokerage. This article sets out what it takes to run a loop nobody is watching. We have not built this configuration and have not verified that it runs. What follows is the published behaviour plus the general conditions a loop of this kind needs. Everything checked as of 6 September 2026.
- Writing in conversation and running a loop are different things
- What a code CAD loop actually requires
- What can serve as a pass/fail test
- Printability is the part the checks cannot reach
- Writing the verification can be harder than writing the thing
- Working with something that asks questions
- What happens if you do not reply
- Keep the failure history on your own side
- How to read the coding numbers
- Do not read a narrow row as a rout
- Write on the assumption that versions move
- Do not build on experimental features
- Where to stop the loop
- What we have not verified
- In short
- Sources
Writing in conversation and running a loop are different things
A boundary first. Writing designs in code while conversing with an AI — prompting, reading what comes back, asking for fixes — is covered in writing code CAD with ChatGPT and Claude. Building solids by addition and subtraction, how to phrase instructions, how to structure variables: that groundwork is there.
This article is about what has to exist so that the loop closes without you in it.
What a code CAD loop actually requires
Strip it down and the loop has four parts. Generate code from a specification. Execute the code. Judge the result mechanically. Feed the judgement back as the next instruction. Three of the four are easy. The third is the whole problem.
While a person is the judge, the criterion can stay in their head. Remove the person and the criterion has to be written down, in a form a machine can evaluate, before the loop starts.
What can serve as a pass/fail test
| Check | What it catches | Cost to build |
|---|---|---|
| Does it parse and render | Syntax errors, unresolved references | Low |
| Does it produce a closed solid | Non-manifold geometry, zero-volume results | Low |
| Bounding box within limits | Parts that will not fit the bed | Low |
| Measured dimensions match the spec | Wrong hole positions, wrong clearances | Medium |
| Mass or volume within range | Wall thickness and infill mistakes | Medium |
| Overhang angles within limits | Shapes that will need heavy support | High |
The first three are cheap and the last is expensive. In practice, order the checks from cheap to expensive and stop at the first failure. There is no point measuring dimensions on something that failed to parse.
Printability is the part the checks cannot reach
There is a limit worth stating plainly. Whether a shape prints well is not a property of the shape alone. The material, the state of the machine, the nozzle diameter, the room temperature. The same geometry gives a different result under different conditions.
So what the loop can deliver is a shape that is dimensionally correct. Whether it prints, and holds up in use, is verified in a separate process. Confusing the two is how you end up with something that passed every check and produced not one usable part.
The workable posture is to aim the net at catching what is obviously wrong, not at certifying what is right. Think of it as: passing does not mean good, failing means bad. Rather than making the mesh ever finer, look at each thing that failed and add a check for it. The net grows faster that way.
Writing the verification can be harder than writing the thing
To be honest about it, the awkwardness of this setup sits on the verification side.
Code that makes a shape can be a few dozen lines when it goes well. Expressing “this shape is correct” in machine-readable form means putting all of your criteria into words. Hole positions, fit clearances, relief cuts, load direction relative to the layer lines. It is the work of writing down as conditions what you had been judging at a glance.
Which is why this configuration only suits making the same kind of thing repeatedly. For a one-off, you would design it yourself in the time it takes to write the checks. For dozens of dimensional variants, comparisons across conditions, or a parameter sweep looking for a best value, the up-front cost is recovered.
As a rule of thumb, if you will run the same verification three times or more, it is worth writing. That is a heuristic, not a measured threshold.
Working with something that asks questions
This is where the current model’s behaviour becomes relevant. The developer states that it uses context to fill in routine gaps and asks focused questions when the answer could change the outcome. It neither queries everything nor pushes on silently.
From inside a loop this cuts both ways. The good side is that it does not halt over trivia — a configuration that waits for a human because a chamfer size was unspecified defeats the purpose of running unattended. The bad side is that it can stop at the point where it asks. A loop you thought was running overnight can be sitting on a question in the morning.
What happens if you do not reply
The published behaviour covers this. In Codex it can ask asynchronously while continuing work that does not depend on your reply. If you do not respond, it proceeds with sensible assumptions where appropriate, but waits for your input on consequential decisions.
Read as a design for unattended running, that is roughly the behaviour you want, and it still leaves you with a question: which of your decisions count as consequential is decided by the model, not by you. So the safe construction is to pin down anything you would consider consequential in the specification itself, rather than relying on being asked about it.
The related improvement is worth noting: the developer says earlier models sometimes treated a steering message as a new goal and lost the original request, and that this one carries new requirements forward without dropping the broader task. In a long loop, that is the difference between a correction and a derailment.
Keep the failure history on your own side
One habit is worth building in from the start. Record every iteration on your side of the loop — the specification, the generated code, which check failed, and what changed next time.
Partly this is so you can resume after a halt. Mostly it is because the failures are the material from which the check set grows. A failure you did not record is one you will meet again, and the second time you will not know it is the second time.
It also gives you the only honest answer to the question of whether the loop is working. Iterations per successful result, trending over weeks, tells you something. A subjective sense that it feels quicker does not.
How to read the coding numbers
| Benchmark | GPT-6 Astra | GPT-5.6 Sol | Best other listed |
|---|---|---|---|
| Terminal-Bench 4.0 | 57.9% | 37.3% | 55.8% (Claude Fable 5.1) |
| DeepSWE v1.1 | 74.1% | 72.7% | 73.8% (Gemini 3.8 Flash) |
| FrontierCode 1.1 Extended | 64.5% | 60.6% | 64.9% (Claude Fable 5) |
| Internal Database Migration | 63.9% | 42.7% | 57.8% (Claude Fable 5.1) |
The eye-catching row is Terminal-Bench 4.0 at 57.9% against 37.3%. But in the same table DeepSWE reads 74.1% against 72.7%, and another vendor is at 73.8% — inside a point.
Do not read a narrow row as a rout
Given a table like this, quote only the wide rows and you can write “dominant”; quote only the narrow rows and you can write “neck and neck”. Both are excerpts of the same table.
The dull practical conclusion is that the size of the gap depends on the kind of task, so you have to look at the row closest to your own use. And a benchmark close to writing designs in code may simply not be in the table. The numbers are a reference; the verdict comes from your own material.
Write on the assumption that versions move
A further practical caution: the surrounding tooling updates constantly.
In the two days spanning release, the coding tool shipped four updates. Support for configuring the model through the API. A correction to the speed-tier description. Another cloud route added. A fix to how the default model is handled. Of these, the speed-tier text originally said “1.5x” and was corrected to “2x” — the developer had it wrong once itself.
Two lessons. If you cite a version number, cite the date you checked it. And hold the assumption that information published right after a release can be corrected; numbers in particular are sometimes fixed quietly.
For anyone building automation there is a further implication. In an environment where the tooling changes four times in two days, anything that leans on fine tool behaviour breaks easily. Configuration key names, the default model, the ordering of options. Fix the input and output formats instead, and the tool in the middle can be swapped without rebuilding around it.
Do not build on experimental features
Related to the same point: anything marked beta, preview or experimental is a poor foundation for an unattended loop. Not because it will not work, but because when it changes, it changes while nobody is watching. A loop that runs overnight has no one there to notice that a flag was renamed.
The rule that follows is narrow and useful: put experimental features where a human sees the output, and keep the unattended path on stable interfaces.
Where to stop the loop
There is one thing you must decide before running anything unattended: when to give up.
“Stop when the checks pass” looks like a design but omits the case where they never do. Checks that are too strict never pass, and the generating side can repeat the same mistake indefinitely. Since nobody is watching, the stopping condition has to be settled in advance.
Three ways to stop:
- By iteration count. Simplest: ten rounds without a pass and it goes back to a human.
- By rate of improvement. Stop when the gap on the failing check stops narrowing between rounds.
- By cost. Stop after a set spend, regardless of progress.
Cost is the one people forget, and it is the one that has a bill attached. The loop is charged for every round it runs. In a configuration where more rounds get you closer to a result, deciding where to stop is the design, not a detail of it. The pricing thresholds that make this bite are set out in where the price table jumps.
In practice, use all three: a hard iteration cap, an improvement check to bail out early, and a cost ceiling as the backstop.
What we have not verified
- We have not built this. Nothing here is a report of a running loop.
- Published benchmark scores are maximum-effort values. What a default configuration returns is not published.
- No benchmark in the tables measures code CAD specifically. Transfer from these numbers to this task is an assumption, not a finding.
- Where the model draws the line on “consequential” — and therefore where it will wait for you — we could not establish from documents.
- Tool behaviour as of a given date is exactly that. Four updates in two days is the environment you are building in.
In short
The obstacle to automating code CAD is not the generation. It is that removing the human means writing down the criterion the human was holding, and the criterion is usually harder to write than the shape.
So build the check set cheapest-first and let it grow from actual failures, expect it to certify dimensional correctness and nothing about printability, and keep the iteration history on your own side because that history is where the checks come from. Assume the model may stop to ask, and pin down in the specification anything you would not want decided for you.
Then decide, before you start it, on three stopping conditions: rounds, improvement, and cost. Unattended does not mean unbounded.



