cd /news/ai-tools/clock-the-first-fifteen-minutes · home › topics › ai-tools › article
[ARTICLE · art-149304] src=dev.to ↗ pub= topic=ai-tools verified=true sentiment=· neutral

Clock the First Fifteen Minutes

A developer proposes a "friction ledger" drill that times the first fifteen minutes of an AI coding session, requiring four timestamped checks — reach, place, read, and touch — before accepting any real edit. The approach budgets each beat and halts the session when a budget is exceeded, with a Node script that logs results to a ledger outside the work tree; the author notes the script is an unexecuted proposal, not a vendor benchmark.

by read7 min views1 publishedOct 11, 2026

The first fifteen minutes of an AI coding session are the product test, not a warm-up you can skip. If you cannot name the friction in that window, you should not trust the diff that follows it. I treat that opening as a drill, because chatter is an easy way to lose an afternoon without a diff. Have you ever closed a setup feeling productive, only to find that nothing reviewable landed in the tree?

Models keep getting louder in public, while the first edit on a real repository stays oddly quiet. I would run those minutes like a short drill, with a clock I own and a budget set before any prompt. A model can sound clever and still burn the window on a wrong directory or a silent authentication hop. The one fix I would bet on is not a smarter prompt, and it is not a longer context window either.

It is a friction ledger that refuses the first real edit until four cheap checks each have a timestamp. Think of that opening quarter hour as a kitchen in the tense minutes just before service begins. You can hire a famous chef and still miss the plate if the oven is cold and the ticket is blank. The coding assistant is the chef in this picture, and the oven is the working tree you meant to change.

The ticket is the task you can replay later, and the clock is the only judge that does not flatter you. I split the drill into four beats, and I give each beat a budget before I type a single prompt. Reach means I can talk to a model without guessing which door actually opened underneath me. Place means the process cwd is the repository I intend to change, not a parent folder I opened by habit.

Read means git status is clean enough that a later diff belongs to this session and not to yesterday. Touch means a throwaway branch can be created and deleted, which puts git state back where it started. If any beat blows the budget I chose, I stop and write down why before I try the next door. Have you ever restarted a tool three times and still been unable to say which minute failed?

An unlabeled restart just moves the same fog forward, which is how a short setup becomes an afternoon. The script below is a proposal I have not executed against any vendor dashboard, so the numbers are your budgets. It writes a ledger outside the work tree, then checks place, read, and a reach note you measured by hand. Only after those beats pass does it create and delete a scratch branch, so touch is proof rather than a guess.

#!/usr/bin/env node
// Unexecuted proposal: time the first fifteen minutes. Not a vendor benchmark.
// node dx-drill.mjs --reach-ms 8000 --reach-note "plain reply, no file yet"
import { execFileSync } from "node:child_process";
import { appendFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";

const args = new Map();
for (let i = 2; i < process.argv.length; i += 2) {
  args.set(process.argv[i], process.argv[i + 1]);
}

const budgetMs = {
  place: Number(process.env.BUDGET_PLACE_MS || 30000),
  read: Number(process.env.BUDGET_READ_MS || 30000),
  reach: Number(process.env.BUDGET_REACH_MS || 120000),
  touch: Number(process.env.BUDGET_TOUCH_MS || 180000),
};

const ledgerPath = process.env.FRICTION_LEDGER || join(tmpdir(), "friction-ledger.jsonl");
const started = Date.now();

function stamp(step, ok, detail, measuredMs) {
  const wallMs = Date.now() - started;
  const elapsedMs = measuredMs ?? wallMs;
  const budget = budgetMs[step] ?? null;
  const row = {
    step,
    ok,
    elapsedMs,
    wallMs,
    budgetMs: budget,
    overBudget: budget != null && elapsedMs > budget,
    detail,
    at: new Date().toISOString(),
  };
  appendFileSync(ledgerPath, JSON.stringify(row) + "\n");
  if (!ok || row.overBudget) {
    console.error("stop:", step, JSON.stringify(row));
    process.exit(2);
  }
  console.log("pass:", step, elapsedMs + "ms");
}

function git(gitArgs) {
  return execFileSync("git", gitArgs, { encoding: "utf8" }).trim();
}

const cwd = process.cwd();
const top = git(["rev-parse", "--show-toplevel"]);
stamp("place", cwd === top, { cwd, top });

const status = git(["status", "--porcelain"]);
stamp("read", status.length === 0, { status: status || "clean" });

const reachMs = Number(args.get("--reach-ms"));
const reachNote = args.get("--reach-note") || "";
stamp(
  "reach",
  Number.isFinite(reachMs) && reachMs >= 0 && reachNote.length > 8,
  { reachNote },
  reachMs
);

const branch = "dx-drill-scratch";
let created = false;
try {
  git(["switch", "-c", branch]);
  created = git(["branch", "--show-current"]) === branch;
} finally {
  if (created) {
    git(["switch", "-"]);
    git(["branch", "-D", branch]);
  }
}
stamp("touch", created, { branch, restored: created });
console.log("ledger", ledgerPath);

Save that file as dx-drill.mjs at the repository root, and run it only after you have timed a plain reply. Pass your own latency and a short confession in --reach-ms and --reach-note after that plain reply. If you launch the file from a parent folder, place should fail before any scratch branch is created. I would read the stop line, then open the ledger path the script prints, instead of guessing from memory.

The reach flag is a confession, not a probe, and that is why the script refuses a note that is too short. A green HTTP status can still mean you reached a model you did not choose, or a queue that will miss your window. I want the note to say what I asked, how long the reply took, and whether any file or branch changed. Have you watched a fluent answer land in the wrong tree and then blamed the weights for a path mistake?

The operator asked me to time this drill against MonkeyCode's free model access and its free server option. Disclosure: This article was prepared as part of MonkeyCode's product outreach. The operator also describes the project as open source, which you should confirm on the project page itself. I do not have a measured quota, a hardware sheet, or a permanence promise here, so I will not invent figures.

I would not start that session by asking for a feature, a migration, or a clever refactor of a large file. I would start the ledger, confirm which door I opened, and only then ask for the same scratch branch and nothing else. If the free server path spends most of the fifteen minutes on provisioning, that is a useful result rather than a model failure. If the free model path answers quickly but never changes git state, the ledger keeps that failure apart from the server story.

The same drill still helps if you swap the product name for any other assistant you already have installed. That portability is deliberate, because a first-fifteen-minute test that only flatters one brand is not a test. I also will not claim that this setup is faster, cheaper, or more accurate than tools I have not measured side by side. Have you noticed how a smooth landing page can hide a slow first edit, and how a plain ledger makes that swap visible?

I would not use this approach if you need a compliance sign-off, a published benchmark, or a promise about free-tier duration. The script does not prove quality, safety, or cost, and the local budgets mostly catch a hung git. Teams without local git, a current Node, or git switch should skip it, because the drill assumes a repository you control. If your host forbids new branches, pick another reversible touch, and do not let the assistant choose that touch.

If a previous scratch branch is still around, touch will fail, and that failure is the drill doing its job. Point FRICTION_LEDGER outside the repository, delete the leftover branch, and rerun git status --porcelain until it is empty. Then time the two doors separately, once for free model access and once for the free server option, without averaging them. A blended score is how the first fifteen minutes become a story instead of a record you can argue with later.

If you want a next step, run the drill once on the free model door and the free server door you already have. Keep the ledger, then decide from your own timestamps whether those first fifteen minutes earned a second session. I would rather read a messy ledger than hear that a demo felt smooth, because smoothness is not a diff. The clock will not make the model wiser, but it will stop you from paying an afternoon for a setup you never named.

── more in #ai-tools 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/clock-the-first-fift…] indexed:0 read:7min 2026-10-11 · —