Skip to content

feat(opencode): add run_in_background to shell tool with auto notification - #47231

Open
Kai-Liu001 wants to merge 3 commits into
anomalyco:devfrom
Kai-Liu001:shell-background-jobs
Open

Kai-Liu001 wants to merge 3 commits into
anomalyco:devfrom
Kai-Liu001:shell-background-jobs

Conversation

@Kai-Liu001

Copy link
Copy Markdown

Issue for this PR

Closes # (no existing issue, happy to file one if useful)

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

The shell tool is synchronous, so long-running commands (dev servers, watch modes, long test suites) block the turn until they exit or time out.

This adds a run_in_background parameter. When set, the command runs via the existing BackgroundJob registry (same one the task tool uses for background subagents), the tool returns immediately with a jobId, and when the command exits its output is injected into the session as a synthetic message so the model gets re-invoked automatically. No polling needed.

Background jobs skip the live metadata streaming and the tool-call abort race, since the tool call is already done by the time the command exits. An explicit timeout is still honored. Gated behind the same OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS flag the task tool uses. Job state stays process-local, consistent with the existing registry.

How did you verify your code works?

  • New integration test in test/tool/shell.test.ts covering the immediate return, the completed job output, the synthetic prompt delivery, and the flag-disabled rejection.
  • Ran the TUI against a real model: sleep 20 && echo ... returned instantly, I could keep chatting while it ran, and the completion notice came back on its own ~20s later.

Screenshots / recordings

Not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@Kai-Liu001

Copy link
Copy Markdown
Author

Heads up for anyone reviewing: #33310 also adds background execution to the shell tool, but stops at launch + a kill tool — there's no completion signal, so the model has to poll or the user has to paste output back. This PR covers the other half: when the command exits, its output is injected into the session and the model is re-invoked automatically. That's the "background launch + completion delivery" combination called out in the TODO at the top of packages/core/src/tool/bash.ts. Happy to coordinate with @Rejudge-F or split/merge the work however the maintainers prefer.

Also: the typecheck/test/nix-eval workflows are stuck at "action required" for this first-time contributor — could a maintainer approve those runs? The suite passes locally (bun run typecheck clean, 25/25 in test/tool/shell.test.ts).

@Kai-Liu001

Copy link
Copy Markdown
Author

Pushed a second commit adding the observation/control half:

  • Background commands tee all output to a log file (logPath in the result metadata), so live progress is readable with the existing Read/Grep tools at any time.
  • New bash_jobs tool: list (id, status, command, log path) and kill (terminates the command's whole process group). Cancelled jobs don't trigger the completion injection.

Tests: 3 new cases in test/tool/bash-jobs.test.ts, extended the background test in test/tool/shell.test.ts with log-file assertions. Full suite green locally.

…ation

Long-running commands can now be launched with run_in_background=true.
The tool returns immediately with a jobId; when the command exits, its
output is injected into the session as a synthetic message so the model
is re-invoked automatically. Gated behind OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS.
Metadata streaming and the tool-call abort race are skipped for background
jobs since the tool call has already completed by the time the command
exits. Timeout stays honored when passed explicitly.
Background shell commands now tee all output to a log file (logPath in
the result and job metadata), so live progress can be inspected anytime
with Read/Grep instead of polling. The new bash_jobs tool lists
background shell jobs (id, status, command, log path) and kills one by
job id, killing the whole process group. Cancelled jobs do not trigger
the completion injection.
bash_jobs now lists both background shell commands (type bash, with log
path) and background subagents (type task, with child session id), and
kill works for both kinds. Subagent cancellation rides the existing
onInterrupt wiring in the task tool.
@Kai-Liu001
Kai-Liu001 force-pushed the shell-background-jobs branch from 9ef8b4f to 2bd2f8a Compare September 7, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant