What happens
--timeout is documented as the fetch budget ({ name: 'timeout', type: 'int', default: 30 } in src/fetch/command.ts), but it appears to apply per attempt rather than to the call as a whole. src/fetch/client.ts retries across tiers — plain, then impit with a chrome profile, then firefox — so a slow or hanging host multiplies the wait.
Measured on current main:
$ time webcmd web fetch --url https://news.ycombinator.com --timeout 10
… 1:08.65 total
68 seconds against a 10 second budget. An unflagged run against the same host exceeded 120s.
Why it matters
Agents use --timeout to bound a step. When it silently runs 7x over, a research loop that budgets a few blocked fetches stalls instead, and in a harness with its own tool timeout the call is killed with no structured error to act on.
Expected
--timeout bounds the whole command. Either divide the budget across the retry tiers or apply it as an overall deadline that aborts the ladder, and surface a FETCH_TIMEOUT-style structured error when it is hit.
What happens
--timeoutis documented as the fetch budget ({ name: 'timeout', type: 'int', default: 30 }insrc/fetch/command.ts), but it appears to apply per attempt rather than to the call as a whole.src/fetch/client.tsretries across tiers — plain, then impit with a chrome profile, then firefox — so a slow or hanging host multiplies the wait.Measured on current
main:68 seconds against a 10 second budget. An unflagged run against the same host exceeded 120s.
Why it matters
Agents use
--timeoutto bound a step. When it silently runs 7x over, a research loop that budgets a few blocked fetches stalls instead, and in a harness with its own tool timeout the call is killed with no structured error to act on.Expected
--timeoutbounds the whole command. Either divide the budget across the retry tiers or apply it as an overall deadline that aborts the ladder, and surface aFETCH_TIMEOUT-style structured error when it is hit.