Repository navigation
Open
Description
[FEATURE]: add wait built-in tool with countdown in footer
Summary
Add a Core built-in wait tool that blocks for N seconds while publishing
Tool.Progress updates, and render a countdown in the TUI footer instead of
the generic spinner.
Why
Claude Code has a WAIT tool that blocks (in tool-call queue, async to the
agent loop) and shows countdown in footer — useful for:
- CI / deployment wait loops (wait N seconds then check status)
- Avoiding busy-poll
bash: sleep 1; check - First real consumer of the
Tool.Progressevent (currently defined but unused)
We already have all the infrastructure:
Tool.Progressevent schema (packages/schema/src/session-event.ts:331-340)- TUI footer spinner (
packages/tui/src/component/prompt/index.tsx:1515-1594) - App reducer already handles
session.tool.progress(packages/app/src/context/server-session-v2-reducer.ts:276) Tool.make+permission.assertpattern (seewebfetch.ts)Effect.genfor time-based orchestration- Async tool execution via
FiberSet.run(packages/core/src/session/runner/llm.ts:278) —waitruns in parallel with sibling tool calls in the same turn, like all other tools
Proposed contract
Input: { seconds: 1..600, reason?: string }
Output: { waited: number, reason?: string }Hard cap 600s to discourage wait(seconds=86400) (Claude Code removed wait
after abuse — same model here).
Implementation sketch
packages/core/src/tool/wait.ts— new built-inEffect.genwith 1Hz ticker publishingTool.Progresswith{ remainingSeconds, totalSeconds, reason }instructured/metadatapermission.assert({ action: "wait", resources: [] })— every call requires approval unless allowlisted (same aswebfetch)- Built-in registered in
packages/core/src/tool/builtins.ts+ new location node
packages/tui/src/component/prompt/index.tsx— matchprogress.structured.type === "wait"→⠋ 12s remaining (reason); fallback to generic spinner for non-wait toolspackages/app/src/...—RunningToolPart(or wherever running tool is rendered) reads metadata; ifstructured.type === "wait"show12s remaining. App reducer already passes metadata through (packages/app/src/context/server-session-v2-reducer.ts:282).- Tests: extend
packages/core/test/session-tool-progress.test.tswith wait-specific cases (cap enforcement, permission gating, progress event cadence)
Out of scope (future)
- Stage 3: URL polling source (
wait({ url, expect: 2xx })) - Stage 4: pluggable sources via
opencode.tools.register
Open questions (to resolve during impl)
- How exactly to publish
Tool.Progressfrom insideTool.makeexecute— the publisher lives inrunner/publish-llm-event.ts; need to verify the channel exposed to tool leaves. May need a new lightweightctx.progress.emit(structured)accessor. - Permission resource for
wait(webfetch uses URL; wait has no resource —[]?). - Footer vs timeline rendering trade-off (TUI has both — pick one or both).
Reacted by Vik
Metadata
Metadata
Assignees
Labels
No labels
Activity
opencodejr commentedon Oct 28, 2026
Thanks for the detailed proposal! You're asking for a built-in
waittool that blocks for a set number of seconds (capped at 600), reports its progress, and shows a countdown like12s remaining (reason)in the TUI footer and the app instead of the generic spinner. That would replacebash sleeppolling in CI and deploy loops.One small correction: tool progress is already used. The subagent tool reports progress, and plugin tools get
ctx.progress(...). So a plugin could already provide awaittool. What it can't do is show the countdown in the footer, because the footer only shows a generic spinner for running tools.Related issues:
wait_for_subagentstoolMaintainers will look at this and decide whether to add it.