all lessons · Context and cost · 7 of 17

Timeouts, stdin, and background jobs

Seventy-four hours of waiting, found in thirty days of logs

A month of agent logs, one question: where did the wall-clock time go?

The answer was not thinking, and it was not typing. It was waiting: six-second commands given two-minute timeouts, and commands that read from standard input sitting there until the ceiling because nothing was ever going to type into them.

Time is the other budget, and it is the one that makes the workflow feel slow even when the tokens are fine. Three rules came out of that month.

Size the timeout to the job

A probe takes ten seconds. A build takes three minutes. A default that covers the build is twelve times too long for the probe, and when the probe hangs, you wait the full default before anyone notices. The rule: short probes get ten to thirty seconds, builds get two to five minutes, and nothing keeps a default it does not need.

This matters more than it sounds, because the agent will hit hung commands more often than you would. It runs things you would not bother to run, against services you forgot were down.

Feed non-interactive commands from nowhere

Any command that might read stdin will, if stdin is a terminal, wait for input that never comes. Remote shells, package initializers, and one of the agent CLIs in non-interactive mode all do this. The fix is one token: redirect standard input from /dev/null. It cannot hang on a prompt it cannot see.

Background anything over a minute

Builds, deploys, long test runs, a second agent doing a batch. Start them detached, keep working, and act on the completion notification. Do not pipe a background job through a filter that only prints at the end; it hides progress until the job finishes and makes a running job look stuck, so you kill it, so it never finishes.

The worst pattern is the polling loop: “check every thirty seconds until done”. Each check is a full turn at full context. A three-minute build polled every thirty seconds costs six turns of re-reading for six lines of “still running”.

Check narrowly while iterating, fully once

Lint the file you touched. Syntax-check the script you edited. Run the one test that covers the change. Then, once, right before commit, run the repository’s full canonical check, which takes minutes. Running the full chain after every edit is the time-budget version of catting a log file into the context: it feels thorough and it is mostly waste.

Match the wait to the work, feed silence to anything that might ask a question, and never sit in a loop watching a job. The agent is patient; you should not let it be.