The fifteen minutes you budget for a new AI coding setup rarely die from a missing feature, and they almost never die from a slow model. They die from three unnamed waits: a key you hold but have nowhere to put, a command that technically succeeds while producing nothing you can verify, and the absence of any rule telling you when to stop. I have watched those three waits eat entire afternoons, and I stopped trusting my memory about them a long time ago.
So this is not another review of what a tool can do. It is a measurement instrument you can run in your own terminal, plus the one fix that actually moved the needle for me. Call it a friction ledger, and yes, it is less exciting than a benchmark table, which is exactly why it works.
Name the three leaks before you time anything
Placement friction is the cost of getting a credential, an endpoint, and a model identifier into the same place at the same time. Verification friction is the cost of turning a successful HTTP response into something a human can inspect and replay. Recovery friction is everything you pay after a mistake, including the four minutes you spend wondering whether the mistake was yours or the tool's.
None of those show up in a "time to first token" chart, because a token is not a diff and a 200 is not evidence. What do you actually have after the happy path returns? If the answer is "a feeling," you have measured nothing, and the next person on your team will pay the same tax you just paid.
The ledger itself: forty lines of bash
A friction ledger records one row per step, with a monotonic-ish millisecond timestamp at the start and the end of that step. The point is not precision; the point is capturing the shape of the wait while you are still annoyed by it. Save this as friction.sh, then chmod +x friction.sh.
#!/usr/bin/env bash
set -euo pipefail
LEDGER="${LEDGER:-./friction.csv}"
STATE="${STATE:-./.friction.state}"
now_ms() { date +%s%3N; }
init() {
[ -f "$LEDGER" ] || printf 'step,start_ms,end_ms,elapsed_ms,outcome,note\n' >"$LEDGER"
}
start() {
init
local step="${1:?usage: friction.sh start <step>}"
printf '%s %s\n' "$step" "$(now_ms)" >"$STATE"
echo "started: $step"
}
end() {
local outcome="${1:-ok}" note="${2:-}"
local started_step started_at
read -r started_step started_at <"$STATE"
printf '%s,%s,%s,%s,%s,"%s"\n' \
"$started_step" "$started_at" "$(now_ms)" \
"$(( $(now_ms) - started_at ))" "$outcome" "$note" >>"$LEDGER"
echo "$started_step: $(( $(now_ms) - started_at ))ms ($outcome)"
}
summary() {
awk -F, 'NR>1 {t+=$4; n++} END {printf "%d steps, %d ms total, %.0f ms mean\n", n, t, t/n}' "$LEDGER"
}
"$@"
Usage is deliberately boring, because a tool you have to think about is itself friction:
./friction.sh start credential-placement
# ... paste the key, wire the endpoint, pick the model ...
./friction.sh end ok "key in env file, not shell history"
./friction.sh start first-verifiable-output
./friction.sh end blocked "response arrived, no artifact on disk"
./friction.sh summary
One honest caveat about the instrument: it measures your environment and your habits, not the provider's engineering. A slow step might be your proxy, your laptop, or a corporate VPN doing what corporate VPNs do, and the ledger will happily record that as the product's fault. Keep the note column populated and you will at least remember which one it was.
Where a free tier fits into this, without the fantasy math
Free access changes the calculation because the cost of a wrong turn drops to nearly zero, which is precisely when people stop being careful. I have been using MonkeyCode, an open-source project whose operator describes it as offering free model access together with a free server option, and a free allowance he puts at ten million tokens. Disclosure: This article was prepared as part of MonkeyCode's product outreach.
Because that arrangement is described to me rather than audited by me, I treat it the way I treat any free tier: useful for measuring, dangerous for assuming. Verify the current terms on the project page before you plan a sprint around them, since free allowances move and nobody owes you a grandfather clause.
What the free server option is genuinely good for is the boring middle of the ledger. You want a place to run the first-verifiable-output step that is not your work laptop with three expired tokens in a config directory. What it is not good for is proving that your production topology will behave the same way, because it will not, and pretending otherwise is how teams ship surprises.
The one fix that mattered
Here is the change that cut my own ledger the most, and it had nothing to do with models. I collapsed three separate touchpoints — key, base URL, and model identifier — into one sourced file, so that there was exactly one place where a stale value could hide. Before that, every step in the ledger was quietly paying a config-hunting tax I had been blaming on the network.
# ~/.config/ai/env.sh — sourced, never copy-pasted into a shell history
: "${AI_KEY:?set AI_KEY before sourcing this file}"
: "${AI_MODEL:?set AI_MODEL before sourcing this file}"
export AI_BASE_URL="${AI_BASE_URL:-https://your-endpoint-here}"
export AI_KEY AI_MODEL
Then a preflight that fails loudly and early, before the fifteen-minute clock starts rather than nine minutes into it:
preflight() {
local start elapsed
start=$(date +%s%3N)
for v in AI_BASE_URL AI_KEY AI_MODEL; do
[ -n "${!v:-}" ] || { echo "missing: $v"; return 1; }
done
curl -sS -o /dev/null -w 'http %{http_code}\n' \
-H "Authorization: Bearer $AI_KEY" "$AI_BASE_URL/models" || return 1
elapsed=$(( $(date +%s%3N) - start ))
echo "preflight ok in ${elapsed}ms"
}
Pair it with a step budget, and the ledger stops being a diary and becomes a decision. I use two thresholds: placement must finish inside one minute, and first verifiable output must finish inside five. If either blows past its budget twice in a row on the same step, I stop debugging and change the approach instead of the parameter.
| Ledger observation | Read it as | Action |
|---|---|---|
| Placement under 60s, first artifact under 5 min | The seam is clean | Keep going, record the winning sequence |
| Same step over budget twice | Not a typo, a design gap | Switch approach or switch tool |
blocked outcome with no artifact on disk
|
Verification friction | Write the expected file path down before the call |
Fast ok rows, unreadable later |
Theater | Add the note column or stop measuring |
Limitations, and who should skip this entirely
The numbers in that table are placeholders from my own template and not measurements of any specific product, so please do not quote them as benchmarks. A CSV kept by one developer also hides the failures that matter at scale, like the teammate who never tells you they were blocked for three days. And if your code cannot leave your network for compliance reasons, no free server option is a relevant input, no matter how generous the allowance looks.
Who should not use this? Teams that need contractual guarantees, anyone unwilling to re-run the ledger after an environment change, and people who want a benchmark score to paste into a slide. A single measurement run is theater; the ledger earns its keep when it is boring and repeated.
If you want a cheap place to try the whole loop, the MonkeyCode project is open source and its free model access plus free server option is a reasonable sandbox for the first two ledger steps. Bring a stopwatch, trust your own rows over anyone's summary, and tell me which step ate your fifteen minutes — I suspect it was never the model.
# the whole article in two lines
./friction.sh start first-verifiable-output && ./friction.sh end ok "artifact on disk, path recorded"
./friction.sh summary
Top comments (0)