The first fifteen minutes of an AI coding session rarely fail because the model is dull. They fail because I leave the terminal, open five tabs, and lose the thread before a single file exists. That scatter is a developer-experience bug, not a talent contest, and it has one mechanical fix.
I used to treat onboarding like homework. I skimmed a README, hunted a dashboard, compared marketing cards, and only then typed a prompt that sounded adult. By minute twelve I owned three half-read pages and zero bytes on disk. Does that feel like building software, or like waiting in a lobby that never calls your name?
The analogy that finally stuck is unkind on purpose. Starting an agent with extra tabs is like brewing coffee while the kettle lives two rooms away. You keep walking, you keep forgetting the mug, and the water is cold when you return. The drink is not the villain. The floor plan is.
So I tore those minutes down the way I would tear down a slow login form. Where did attention leak first? Which click never produced a path in the repo? What would a receipt look like if the session had to tell the truth out loud?
Minute one is usually identity theater. A cloud account, an API key, a billing profile, or a waitlist appears, and the browser wins before git status even runs. Minute four is documentation gravity, because every heading promises a better default if I read just one more paragraph. Minute nine is the fake start: a clever prompt in a chat box that still has no cwd, no branch, and no proof anything on the other side is awake.
The one fix that mattered was rude. I refused to open a browser until a local receipt file existed in the repo I claimed I would touch. The receipt is not a manifesto. It is a timestamp, a git head, a working directory, and a one-line note that names the scratch path I intend to use.
Disclosure: This article was prepared as part of MonkeyCode's product outreach. I point that scratch path at MonkeyCode when I need free model access and a free server option, because those two facts keep a checkout form from competing with the repo during the fragile window. I am not selling a latency number. I am protecting a quarter hour that used to vanish into tabs.
The file lives as an ignored artifact, because session noise does not belong in a pull request. A small script writes it, prints it, and exits nonzero if git is missing or the directory is not a repository. After that, the agent may talk. Before that, the agent is just another tab with better grammar.
#!/usr/bin/env bash
# session-receipt.sh — stay in this window until a receipt exists.
set -euo pipefail
receipt=".agent-receipt.json"
scratch_host="${SCRATCH_HOST:-}"
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "not a git repo; the agent does not get a workspace guess" >&2
exit 1
fi
head=$(git rev-parse --short HEAD)
branch=$(git branch --show-current)
cwd=$(pwd)
now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
if [[ -z "$scratch_host" ]]; then
host_note="unset — export SCRATCH_HOST before the agent runs"
else
host_note="$scratch_host"
fi
cat > "$receipt" <<EOF
{
"written_at": "$now",
"cwd": "$cwd",
"branch": "$branch",
"head": "$head",
"scratch_host": "$host_note",
"rule": "no browser until this file exists"
}
EOF
echo "receipt written: $receipt"
cat "$receipt"
If you want a slightly stricter gate, reject a receipt older than fifteen minutes. Stale files are how a lunch break becomes a write into the wrong tree. I learned that after an agent cheerfully patched a directory I thought I had already closed, because my shell had never left the previous job.
#!/usr/bin/env bash
# refuse-stale-receipt.sh — a quiet file can still be a lie.
set -euo pipefail
receipt=".agent-receipt.json"
max_age_seconds=900
if [[ ! -f "$receipt" ]]; then
echo "no receipt; stay in this window and run session-receipt.sh" >&2
exit 1
fi
written=$(python3 - <<'PY'
import json, datetime, sys
with open(".agent-receipt.json") as f:
data = json.load(f)
written = datetime.datetime.strptime(data["written_at"], "%Y-%m-%dT%H:%M:%SZ")
age = (datetime.datetime.utcnow() - written).total_seconds()
print(int(age))
PY
)
if (( written > max_age_seconds )); then
echo "receipt is ${written}s old; rewrite it before the agent speaks" >&2
exit 1
fi
echo "receipt is fresh (${written}s)"
Notice what these scripts refuse to do. They do not pick a model by brand. They do not invent a throughput claim I cannot measure from this chair. They do not scrape a status page I have not opened, because opening that page is the original bug. They only prove I stayed in one window long enough to leave a paper trail.
Once the receipt exists, the agent's first command should be boring. I ask it to read the file back, print the cwd, and stop. If it cannot cat the receipt, the session is not onboarded, and I do not negotiate. That sounds petty until a tool invents a workspace because the real one was a single cd away.
# The first agent command I allow after a fresh receipt.
# Label: this is a workflow, not a captured production log.
cat .agent-receipt.json
pwd
git status --short
# If any line disagrees with the receipt, kill the session.
Why does a free server belong in a teardown about tabs? Because the tax is usually a money tab wearing a technical costume. I open pricing when I am unsure the loop will round-trip at all. A free server lets me finish that round-trip without a card form sitting next to the editor. Free model access does the same job for the completion path, so I am not comparison-shopping in the middle of a sentence I have not finished.
This is still a constraint, not a charm. A free path can be busy, rate-limited, or a poor home for private source. I treat it like a loaner laptop: useful for proving the ritual, dangerous as a silent production dependency. If your company forbids unknown hosts, run the same receipt against a box you already operate and do not pretend the habit requires a vendor.
Who should skip this? Anyone already inside a locked IDE with a blessed proxy and a known toolchain. Anyone pairing on a shared machine where a receipt would leak a path they cannot show. Anyone hoping a timestamp will replace tests. The receipt proves presence, not correctness, and mixing those two is how you ship a confident mess.
I still break the ritual when I am tired. I open one docs tab just to copy a flag, and the fifteen minutes evaporate like they always did. The difference is I can see the failure without a debate. No receipt means I wandered. A stale receipt means I wandered later. Either way the clock is no longer a vibe I argue with after the damage.
Keep the script ugly if you try it. Pretty onboarding is how the tab tax sneaks back in wearing a checklist. One window, one receipt, then the agent. Tomorrow, count the minutes before that file appears. If the number is embarrassing, the model was never the bottleneck.
Top comments (0)