Write one prompt that recreates this repo's application from an empty folder, then keep testing it until the rebuild matches the original on every check. The test is real: a builder that has never seen the repo gets only the prompt, builds once with no follow-ups, and a separate checker compares the result to the original. Every miss goes back into the prompt. The loop ends when the prompt passes every check twice in a row, or when it stops improving and you report what is still missing.
When to use
- "Make a one-shot prompt for this app" or "can this repo be rebuilt from one prompt?"
- Someone wants a portable spec of what an app does, proven rather than guessed.
- Before a rewrite or a stack change, to pin down the behaviour that must survive.
Steps
- Map the original. Read the repo and run it. List the stack, every screen or route, every user action, the data model, outside services, config and the existing tests. Ask the owner which differences are allowed (stack, styling, wording, internal structure); the default is that what a user or caller can see must match and the internals may differ.
- Write the parity checklist in
one-shot/checklist.md: numbered checks a stranger could verify by using both apps, such as "POST /todos with an empty title returns 400 and the messageTitle is required" or "the empty state readsNo projects yetwith a New project button". Cover each route, each action, each error state, layout at desktop and phone width, and data that survives a restart. Reuse the repo's own tests where they test behaviour. Capture screenshots and sample responses from the original as the reference. - Draft the prompt in
one-shot/PROMPT.md: the goal, the stack and versions, data model, every screen and endpoint with exact copy, colours and error text, setup and run commands, and how the builder should check its own work before finishing. Set a length cap with the owner (default 15,000 characters). - Run a fresh build. Start a new agent session in an empty folder with no access to the repo, memory or earlier runs. Send the prompt as one message. Answer nothing during the run; a question from the builder counts as a miss in the prompt. Save the result under
one-shot/runs/<n>/. - Check it with a separate checker, never the builder. Run the original and the rebuild side by side, go through every check, and mark each pass or fail with evidence (a command and its output, or a screenshot pair). Score passed over total.
- Trace each failure to the prompt: missing, ambiguous, contradicted, or ignored. Fix the prompt with the smallest general instruction that would have prevented it. Log the round in
one-shot/log.md: score, failures, prompt changes. - Loop from step 4 with a brand-new builder each time. Rerun every check, not just the ones that failed.
- Stop when a run scores 100%, then confirm with one more fresh build; both must pass. Also stop after 10 rounds, or after 3 rounds with no score gain, and report the checks that keep failing and why.
Rules
- The builder sees only the prompt. No repo, no files, no hints, no help mid-run.
- Never edit, drop or soften a check to get a pass. Change the prompt, not the test.
- No pasting source files into the prompt. Exact strings, colours, schemas and sample data are fine; whole functions are not.
- Never put secrets in the prompt. Name each env var and say where its value comes from.
- Use the same builder model and tool every round, and record it in the log.
- "Perfect match" means every check passes on two consecutive fresh builds, not that the code is identical.
Report
When the loop ends, give the owner:
- The final
one-shot/PROMPT.md, its length and the builder it was proven on. - The score per round as one line each, for example
Round 3: 41/47. - Any checks still failing, each with its cause and what a human would have to decide.
- The command to run a fresh build again, so the prompt can be re-proven after the app changes.
Writing good checks
- One observable fact per check. "The settings page works" is not a check; "saving a blank display name shows
Name can't be emptyunder the field" is. - Prefer checks a script can run (an HTTP call, a test, a CLI command) and fall back to screenshots for layout.
- Include the unhappy paths: bad input, empty lists, a missing env var, a network failure, a second user.
- Weight nothing. A wrong error message counts the same as a missing page, because the prompt has to carry both.
Fixing the prompt
- Missing: the prompt never said it. Add it in the section it belongs to.
- Ambiguous: two readings were possible. Replace it with the exact value or an example.
- Contradicted: two lines disagree. Delete one.
- Ignored: the prompt said it and the builder skipped it. Move it higher, make it a numbered requirement, or add it to the builder's own final self-check list.
- When the prompt nears its length cap, cut prose before facts: tables of routes, fields and strings carry more per character than paragraphs.