Skip to content

Shell wrappers: a plugin-settable per-call "run to completion" flag, and an event when a promoted task ends #640

Closed as not planned

Description

@iceteaSA

Summary

A plugin that wraps the shell tool can't make one call run to completion, and can't tell when a promoted call really ends. This matters for wrappers that must clean up after the command: for example, a sudo wrapper that removes cached credentials, or a redaction step on the final output.

Today a foreground call returns before the command exits in three cases:

The only ways to prevent this are global: bash.background: false (#124) or bash.detach_on_user_message: false. A plugin can't set them for one call, and turning them off for every command changes the agent experience for the session. The plugin's own cleanup (its finally after execute returns) therefore runs while the command is still running.

Proposal

  1. A per-call argument a plugin can set in tool.execute.before, for example detach: "never", meaning: no auto-promotion and no detach on messages. The command runs until it exits or reaches its timeout. Agents need not see the argument; it is enough that a plugin can set it.
  2. A plugin-visible event when a promoted or background task ends: task id, session, exit code or signal, and a reference to the final output. A wrapper can then run its cleanup at the real end.

Checked on main (da592c3): the shell's agent arguments are command, timeout, workdir, description, wait, background, pty, ptyRows, ptyCols, compressed, sandbox. The internal block_to_completion the plugin computes (tools/bash.ts:720) can't be set from outside. Related: #398 (a config cap for wait: true).

Activity

  1. aft-alfonso commented on Oct 23, 2026

    @aft-alfonso

    Thanks for laying out the cases.

    We've decided not to add plugin-only per-call flags to the shell tool, so a detach: "never" argument isn't planned, and neither is a plugin-visible completion event.

    For cleanup that has to run when the command really ends, put it in the command itself, for example sudo -A make install; sudo -k, or use a trap in a script. It then runs at the command's real exit whether or not the call was moved to the background, and the agent still gets a normal completion.

    For the sudo case specifically, we're looking at handling sudo approval in AFT itself, so a wrapper wouldn't need to manage cached credentials. There's no timeline for that yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions