DEV Community

Quinn Wang
Quinn Wang

Posted on

Clock the Blocked Minutes, Not the Blocked Steps

The number that predicts whether a newcomer ships in week one is not install time; it is the minutes they spend blocked on another human. I have watched teams cut a twelve-step setup down to four and still lose the new developer, because every remaining step ended with the same sentence: ask someone for access. So before you tune another install script, answer a less comfortable question — do you actually know which of those first fifteen minutes were spent waiting on a machine, and which were spent waiting on a person?

That split matters more this year than last, because most of the noise around AI coding tools is about machine speed. Delete ten seconds of inference latency and nobody notices; delete a forty-minute permissions handoff and the entire first day changes shape. Which is why I now log onboarding friction as two separate clocks, and why the harness below is the only setup tool I keep re-using across projects instead of rewriting.

Two clocks, one TSV row

The first clock is machine wait: package installs, cold starts, image pulls, queue time, token generation. The second is human wait: the Slack message asking for a repository invite, the review of your service account request, the "hey, does anyone know how staging is seeded?" thread. Machine waits feel expensive because they are visible in a terminal, but they are short, repeatable, and usually fixable by caching; human waits are invisible, unbounded, and they are the part people actually remember about their first day.

So the artifact here is deliberately boring. It is a tiny shell library that wraps a command, records a start and end timestamp in milliseconds, and tags the block as human or machine. You run it around each phase of a first-run session, you get a TSV file, and you get ratios instead of anecdotes.

#!/usr/bin/env bash
# frictionlog.sh — two clocks for a first-run session: machine wait, human wait.
# needs: bash, python3 (for portable millisecond timestamps)
set -uo pipefail
LOG="${FRICTION_LOG:-friction.tsv}"
[ -f "$LOG" ] || printf 'phase\twaiting_on\tstart_ms\tend_ms\n' > "$LOG"

now_ms() { python3 -c 'import time; print(int(time.time() * 1000))'; }

block() {            # block <human|machine> <phase> -- <cmd...>
  local waiter="$1" phase="$2"; shift 2
  [ "${1:-}" = "--" ] && shift
  local start; start="$(now_ms)"
  if [ "$#" -gt 0 ]; then "$@" || true; fi
  printf '%s\t%s\t%s\t%s\n' "$phase" "$waiter" "$start" "$(now_ms)" >> "$LOG"
}

begin() { __waiter="$1"; __phase="$2"; __start="$(now_ms)"; }   # open a wait with no command
end()   { printf '%s\t%s\t%s\t%s\n' "$__phase" "$__waiter" "$__start" "$(now_ms)" >> "$LOG"; }
Enter fullscreen mode Exit fullscreen mode

The begin/end pair exists because the worst waits have no command to wrap — the command is wait for a reply. You call begin human "secrets: ask platform team" when you send the message and end when access lands; one open human wait at a time is realistic enough for onboarding. A session then looks like this, and yes, it is meant to look unglamorous:

source ./frictionlog.sh
export FRICTION_LOG=run1.tsv

block machine "clone"         -- git clone --depth 1 git@github.com:acme/webapp.git
block machine "deps/install"  -- npm ci --no-audit --no-fund
begin human   "secrets: ask platform team"      # send the message
# ... coffee, hopefully ...
end
block machine "first build"   -- npm run build
Enter fullscreen mode Exit fullscreen mode

Reading the file instead of arguing about it

A TSV that nobody reduces is just a diary, so here is the whole analysis step in awk — no dashboard, no vendor, no new dependency. It prints total seconds per phase and the share of that phase attributed to a human:

awk -F'\t' 'NR > 1 {
  d = ($4 - $3) / 1000
  total += d
  phase[$1] += d
  if ($2 == "human") human[$1] += d
}
END {
  for (p in phase)
    printf "%-30s %8.1fs   human-blocked %5.1f%%\n", p, phase[p], 100 * human[p] / phase[p]
  printf "%-30s %8.1fs\n", "TOTAL", total
}' run1.tsv
Enter fullscreen mode Exit fullscreen mode

Here is illustrative output showing the shape of a result, not a benchmark of any tool or machine: secrets: ask platform team at roughly 2410s and 100.0% human-blocked, deps/install at 74.2s, first build at 38.9s, first test at 11.6s. Look at that ratio for a second — was your last onboarding fix aimed at the 74 seconds or at the 40 minutes? The reducer answers that in one line, and it is very hard to argue with a number you produced yourself in your own repository.

One discipline point I keep relearning: measure the second run, not the first. The first run is dominated by one-time state and flatters whatever you already optimized, while the second run shows what a returning developer pays every single day. Keep both files, compare them, and be honest about which number your team is actually paid to care about.

The one fix that mattered

In the session above, the fix was not caching and it was not a new devcontainer. The fix was replacing "ask a person for credentials" with "start in a throwaway environment that needs no credentials to build" — a disposable box plus a read-only fixture beats a faster package manager, because it converts a human wait into a machine wait you can queue and forget.

That is the honest place where MonkeyCode's free model access and free server option enter this workflow, and it is a narrower claim than a launch post would make. For the eval-shaped part of onboarding — read this file, write a test, explain this stack trace — a free sandbox with a free token allowance removes two waits that normally stall the first hour: waiting for budget approval, and waiting for someone to provision a machine. Disclosure: This article was prepared as part of MonkeyCode's product outreach. The team advertises a free allowance on the order of ten million tokens and a free server option at the time of writing; that number is exactly the kind of thing that changes, so read the project page before you size a plan around it, and do not treat my prose or this post's date as the source of truth.

I would also keep the open-source claim practical rather than romantic. Being able to read the implementation is genuinely useful when you need to know what leaves your machine, but it is not a security review, and it is not an SLA.

Who should not use this

If your repository needs production credentials to build, a free disposable environment is not your answer and no amount of free tokens changes that — decouple the build first. If you handle regulated data, run latency-sensitive CI, or need uptime guarantees for a demo, a free tier is the wrong layer and a boring paid box is the correct choice. And if your measured human-blocked share is above forty percent, stop shopping for tools entirely, because your bottleneck is a permission model and every new AI feature is a distraction from it.

Which brings me back to this week's loudest argument about AI and jobs. The interesting question is not whether a model can do the work; it is which waits your team has quietly normalized for years and stopped seeing. Clock both kinds, publish the ratio where the team can read it, and let the numbers pick the fix — would you rather save ten seconds of inference, or one expensive afternoon of asking?

If you want to run the harness against something disposable, the free tier is a fair place to try it; bring the TSV back with you, not just the vibes.

Top comments (0)