Skip to content

Feature request: expose subprocess PID from SubprocessCLITransport for cleanup #1370

@kryvel

Description

@kryvel

Context

When using claude-agent-sdk via sdk_query(), the underlying SubprocessCLITransport spawns a claude CLI child process. If the calling code needs to cancel (timeout, SIGTERM, etc.), the async generator can be aclose()'d, which triggers SubprocessCLITransport.close()process.terminate().

However, close() has no bounded wait after terminate() and no SIGKILL fallback. If the CLI process ignores SIGTERM (e.g. stuck in a network call), close() hangs and the process becomes orphaned.

Current workaround

We extract the PID by walking async generator frame internals:

def _extract_sdk_pid(gen):
    frame = getattr(gen, "ag_frame", None)
    for val in frame.f_locals.values():
        inner_frame = getattr(val, "ag_frame", None)
        transport = inner_frame.f_locals.get("chosen_transport")
        proc = getattr(transport, "_process", None)
        return proc.pid

This is fragile and depends on SDK internals.

Feature request

  1. Expose transport.pid or transport.process as a public property on SubprocessCLITransport so callers can safely extract the PID for cleanup.

  2. Add a bounded wait + SIGKILL fallback to SubprocessCLITransport.close() so callers don't need to implement their own cleanup. Something like:

    def close(self, timeout=10):
        self._process.terminate()
        try:
            self._process.wait(timeout)
        except subprocess.TimeoutExpired:
            self._process.kill()
  3. Consider start_new_session=True in Popen() so os.killpg() can kill the entire process group (CLI spawns node.js children).

Environment

  • claude-agent-sdk 0.1.58
  • Python 3.12
  • Docker (Linux containers)
  • Use case: FastAPI sidecar service wrapping SDK for concurrent LLM completions

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions