Three pillars, and what each one is missing
Dex is not a new idea. It is three existing ideas — a bash loop, a spec workflow, and an SDK — each of which is most of an autonomous coding system and none of which is all of it. The interesting part is the shape of the holes.
There is a particular kind of project that exists because three other things almost worked.
Dex is a desktop app that takes a description of a project and builds it, feature by feature, while you are not watching. Nothing in it is a new invention. It is a bash loop somebody else wrote, a spec workflow GitHub published, and an SDK Anthropic ships — and the only design work I did that I would call original is deciding which hole each one fills in the other two.
That is worth writing down, because the holes are not obvious until you have run all three into a wall.
Pillar 1: the loop
Geoffrey Huntley’s Ralph Wiggum is four words of bash and one genuinely good idea:
while :; do cat PROMPT.md | claude ; done
Run the same prompt forever. Each iteration gets a fresh context window, reads the current state of the project off disk, picks the most important outstanding thing, does it, commits, and exits. Then it happens again.
The idea people miss is that the repetition is not the point — the amnesia is. A loop that re-ran the same prompt while accumulating context would just be a long session with extra steps. What makes it work is that iteration n+1 starts clean and re-derives the situation from the filesystem, which means it is never carrying iteration n’s dead ends, abandoned theories, or half-corrected misreadings. Convergence comes from repeatedly reading the truth, not from remembering the journey.
Two consequences I inherited wholesale. Context isolation — a fresh window per unit of work, because quality degrades long before the window is full. Self-improvement through the filesystem — durable notes accumulate in a file each iteration reads, so the loop gets better at this project over time without anything being remembered.
What Ralph does not have: any opinion about what to build. It picks its own next task from a free-form list, which means it will happily build the wrong thing with great enthusiasm, and you will find out in an hour. There is no UI, no abort, no cost ceiling, no notion of a failure that should change the plan. It is a bash script, and it is meant to be.
Pillar 2: the specs
Spec-kit is GitHub’s take on specification-driven development: the spec is the primary artifact and code is its output. It ships a templated workflow of slash commands, each producing a structured file:
| Artifact | What it pins down |
|---|---|
constitution.md |
Project-wide principles every feature must obey |
spec.md |
User stories and acceptance criteria for one feature |
plan.md |
Technical approach and architecture decisions |
tasks.md |
Dependency-ordered, individually actionable tasks |
Dex does not reimplement any of this. It literally drives the slash commands —
the entire specify stage prompt is one line:
export function buildSpecifyPrompt(featureName: string, featureDescription: string): string {
return `/speckit-specify ${featureName}: ${featureDescription}`;
}
The reason this matters for autonomy is narrower than “specs are good practice”.
An unattended loop needs a definition of done that it did not write during the
same breath as the code. Acceptance criteria fixed in spec.md before
implementation starts are something the verification stage can be measured
against. Ask an agent to both build a thing and decide whether it is finished in
one context and it will always say yes.
What spec-kit does not have: the loop. It is a sequential, human-driven
workflow — someone runs /speckit-specify, reads the output, runs
/speckit-plan, and decides what happens next. There is no gap analysis, no
recovery when a phase produces something wrong, no mechanism for going round
again.
Pillar 3: the control surface
The Claude Agent SDK turns “a Claude Code session” into something a program can hold:
for await (const msg of query({
prompt,
options: {
maxTurns: 200,
settingSources: ["project"],
hooks: { PreToolUse: [...], PostToolUse: [...] },
},
})) { /* … */ }
Three things here are load-bearing for Dex specifically. Hooks make every
tool call, thinking block and subagent spawn observable, which is the difference
between an autonomous run and a black box. settingSources: ["project"] means
the agent picks up the target repository’s own CLAUDE.md and rules — the
project governs the agent, rather than Dex imposing one house style on every
project it touches. And an abort signal makes Stop mean something, mid-flight.
What the SDK does not have: any opinion at all. It is a library. It does not know what a stage is, when to run one, what to do when one fails, or what “finished” means.
The synthesis, stated as three repairs
Put plainly, each pillar patches the hole in another:
| Hole | Filled by |
|---|---|
| Ralph picks its own work → builds the wrong thing | spec-kit’s specs and acceptance criteria, extracted once into an ordered manifest |
| Spec-kit needs a human to advance each phase | Ralph’s loop, with a gap-analysis stage as the thing that decides what happens next |
| Neither has abort, cost tracking, or observability | the SDK’s hooks, caps and abort signal, wrapped in a desktop UI |
The result is a nine-stage cycle — clarify, constitution, manifest extraction,
then per feature: gap analysis, specify, plan, tasks, implement, verify,
learnings — where every stage is a separate query() with a clean context, and
everything that survives between them lives on disk.
There is also a fourth thing that emerges only from the combination, and it is the one I would have predicted least: failure becomes a decision rather than an exception. Because specs, plans and tasks are all durable files, “this feature failed” is a state you can act on instead of a stack trace. Dex counts:
export type FailureThresholdOutcome =
/** 3 replan failures — feature abandoned; caller advances the cycle and continues. */
| { kind: "skip" }
/** 3 implement failures — caller forces `decision` to REPLAN_FEATURE. */
| { kind: "replan" }
| { kind: "proceed" };
Three failed implementations means the plan is probably wrong, so regenerate it. Three failed replans means the feature is probably wrong, so mark it skipped, log it, and move to the next one rather than burning the remaining budget on a wall. None of the three pillars gives you that alone; it needs durable specs and a loop and a place to put counters.
What the combination costs
A post that lists three wins and stops is an advertisement, so here is the bill.
Nine stages is a lot of fixed overhead. Every feature pays for gap analysis, specify, plan, tasks, implement, verify and learnings whether it needs them or not. For a feature that is genuinely one file and twenty lines, the ceremony costs more than the work — you are paying six agent invocations to justify one. Dex earns its keep on multi-feature projects built unattended over hours; for “add a field to this form”, opening Claude Code and typing is strictly better and I do not pretend otherwise.
Fresh context is not free. Context isolation trades tokens spent remembering for tokens spent re-reading. Each stage re-derives what it needs from disk, which means the same files get read many times across a run. That trade is excellent when a session would otherwise degrade, and simply wasteful when it would not.
Spec-driven means spec-shaped. Everything the loop builds is something that could be expressed as a feature with acceptance criteria before any code existed. Exploratory work — where you do not know what you want until you see the wrong version — fits this badly. The manifest is extracted once and frozen, and that is exactly the property that makes it reliable and exactly the property that makes it inflexible.
Everything after this post is a consequence of one of those three pillars, or of the friction between them. Dex is on GitHub — Electron, React, the Claude Agent SDK, no database, all state in files and git refs.
Next: one agent per stage — what context isolation looks like when you build a whole architecture on it, and what each of the nine stages actually leaves behind on disk.