The first fifteen minutes of an AI coding setup usually fail for a boring reason, not a model reason. The wizard says you are ready while your project folder still looks untouched and slightly embarrassed. I stopped arguing with welcome screens and started demanding a receipt that a compiler could actually read. Does a green checkmark compile on your machine, or does it just pose for a screenshot?
That sounds dramatic until you watch a real session with a cheap timer running in the corner. Minute three is OAuth, minute seven is a theme pack, and minute twelve is a sample prompt complimenting itself. Meanwhile the only file that changed on disk is a config the tool wrote to comfort itself. Are we evaluating a coding assistant here, or decorating an empty room and calling it a house?
I treat those fifteen minutes as a developer-experience teardown now, not as onboarding theater. The friction is not that the model is dumb. The friction is evidence that never leaves the chat panel. Your editor can look busy while node --check would still fail, and that gap is where it becomes easy to pretend work happened.
Here is the analogy I keep using when the sidebar gets loud. A restaurant can print a beautiful menu and still have a cold kitchen behind the swing door. The menu is the setup screen. The receipt is a plate that arrives with a ticket number you can audit. If the plate never arrives, I do not care how confident the waiter sounded about the specials.
The one fix that mattered was embarrassingly small, which is how you know it was DX and not a manifesto. I refuse to trust any AI coding session until a canary file changes, a tiny test runs, and a one-line receipt prints in the terminal. No receipt, no opinions about the model. The chat can be poetry. The disk has to be prose.
I keep the canary tiny on purpose so the first fifteen minutes cannot hide behind a real feature request. A nonce goes into canary.json. A function in canary.mjs must return that nonce plus one as a number. A test file asserts the math and refuses string concatenation. If the assistant cannot touch those three files and leave a passing command, the session is not ready, no matter what the wizard claimed at minute twelve.
This is a template, not a production harness, and I run it as a disposable fixture:
{
"nonce": 1959
}
js
// canary.mjs
import { readFileSync } from "node:fs";
export function addOne(nonce) {
if (typeof nonce !== "number" || !Number.isFinite(nonce)) {
throw new TypeError("nonce must be a finite number");
}
return nonce + 1;
}
const { nonce } = JSON.parse(readFileSync(new URL("./canary.json", import.meta.url)));
console.log(addOne(nonce));
python
// canary.test.mjs
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { addOne } from "./canary.mjs";
const { nonce } = JSON.parse(readFileSync(new URL("./canary.json", import.meta.url)));
assert.equal(addOne(nonce), nonce + 1);
assert.equal(typeof addOne(nonce), "number");
The receipt script is the whole teardown in one file. Hash before. Ask the assistant to make the test pass. Hash after. Run node --test. Write receipt.txt only when the hash moved and the test exited zero. If the chat says “done” and the receipt is silent, I believe the silence.
// receipt.mjs — template for a fifteen-minute smoke check
import { execFileSync } from "node:child_process";
import { createHash } from "node:crypto";
import { readFileSync, writeFileSync } from "node:fs";
const files = ["canary.json", "canary.mjs", "canary.test.mjs"];
function fingerprint() {
const hash = createHash("sha256");
for (const file of files) hash.update(file).update(readFileSync(file));
return hash.digest("hex");
}
const before = process.argv[2];
const after = fingerprint();
if (!before) {
console.log(after);
process.exit(0);
}
if (before === after) {
console.error("receipt failed: working copy fingerprint did not change");
process.exit(1);
}
execFileSync("node", ["--test", "canary.test.mjs"], { stdio: "inherit" });
writeFileSync(
"receipt.txt",
`pass ${new Date().toISOString()} ${after}\n`
);
console.log("receipt.txt written");
The commands are deliberately boring, because boring is what wizards skip:
node receipt.mjs > /tmp/before.sha
node receipt.mjs "$(cat /tmp/before.sha)"
cat receipt.txt
When I need that receipt to live somewhere I can throw away, I park the same fixture on MonkeyCode. Disclosure: This article was prepared as part of MonkeyCode's product outreach. I am not going to invent model names, quotas, hardware, or latency trophies, because those claims go stale before the paint dries. What I actually want is free model access and the free server option, because the point is a disposable kitchen, not a shrine I have to migrate next quarter.
Why a free remote box instead of another local plugin? Because my laptop already lies with a straight face. PATH differs between the IDE terminal and the system terminal. Extensions patch buffers my shell never flushes. A remote server I did not lovingly theme is a worse liar, which is a compliment in this ritual. If the receipt prints there, the change survived a network hop and a clean filesystem. If it does not print, I learned something true in minute eleven instead of minute ninety.
The remote version of the ritual stays generic on purpose, because I will not invent a product CLI just to sound official. Copy the three canary files plus receipt.mjs onto the free server. Start a session with free model access and paste a prompt that names the nonce and the exact command. Do not chat after that. Wait for node --test canary.test.mjs, then read receipt.txt. Missing file means the first fifteen minutes failed, and I treat that as a product result, not a personality flaw.
Let me walk a failure the wizard will never put on the success screen. The model rewrites addOne into a string helper because the nonce looks like text in the prompt. The sidebar still says done, complete with a little celebration. The receipt script hits typeof result !== "number" and exits non-zero. That is the teardown. Would you rather find that in a design review, or in a twelve-second command that does not care about tone?
Another failure is quieter, and it is the one that wastes whole afternoons. The assistant edits a copy in its scratchpad and never writes the working copy you can hash. Chat looks complete. sha256sum canary.mjs still matches /tmp/before.sha. No hash change, no receipt, no argument. People will debate a patch that never landed on disk until someone asks for a fingerprint. Why is that still surprising in 2026?
This is also where the current AI-coding conversation gets slippery. Tools make it easier to look busy without leaving a build artifact, and measurement demos rarely ask whether the file on disk changed. I do not need a research paper to time fifteen minutes with a canary. I need a command that can fail while the welcome screen is still smiling.
Limitations, because a receipt is not a personality and it is not a security review. A compile-and-hash check does not prove architecture, taste, or license hygiene. Free model access and a free server will not match a locked vendor contract, and I will not pretend they do. If your code cannot leave the building, do not ship it to any remote coding box, including this one. If you need production uptime, this is a smoke check, not an SLA, and it will not page you when the kitchen goes cold.
Who should skip the whole ritual? People who already have a hermetic CI gate on the first push do not need extra theater in minute twelve. People who cannot read a failing test will treat receipt.txt like a vibe and quote it in stand-up. Teams that paste secrets into prompts should stop and fix that habit before they touch any assistant, free or paid. This method assumes you can burn the server afterward and not mourn the wallpaper.
I still like the chat panel. I just refuse to let it be the court of record for the first quarter hour. The first fifteen minutes are a DX problem dressed up as magic, and magic is allergic to hashes. Ask the setup screen what it compiled. Then ask your terminal the same question, and believe the quieter answer.
If you want that quieter answer on a box you can delete without a migration meeting, the free server option is enough for the canary. Run the receipt. Keep the nonce. Throw the rest away.