You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Request a public pid (and ideally process) property on SubprocessCLITransport so external orchestrators can manage the CLI subprocess without reaching into private attributes.
Why this needs a tracking issue
The request is currently fragmented across multiple artifacts in different repos, with no canonical place to track demand or coordinate resolution:
anthropic-sdk-python#1370 — original request. Closed with a redirect to claude-code/issues, though the code actually lives here in claude-agent-sdk-python. Hence the cluster of misfiled PRs.
anthropic-sdk-python#1431 — open PR that attempts to add pid to SubprocessCLITransport in the wrong repo (the class doesn't exist there).
This issue is a canonical home for the request. The two open PRs in this repo (#819, #995) both close it; maintainers can pick one and close the other.
Use case
Distyl.ai operates a coding-agent platform that runs the Claude Code CLI under a per-PID credential proxy. Inbound HTTP from the agent subprocess is intercepted by a local mitmdump that identifies the calling process via kernel-attested PID and injects the right user's credentials. The subprocess never sees real secrets.
To register credentials with the proxy, we need the CLI subprocess PID. Today we reach for it like this (paraphrased from our runtime):
Three levels of getattr against private attributes, defensively wrapped. Brittle to any internal refactor. A public property would let us write pid = self._sdk_client.transport.pid and remove the defensive scaffolding.
The original requester (anthropic-sdk-python#1370) needed it for cancel-cleanup; we need it for credential injection. Both are valid orchestrator concerns the SDK currently makes harder than necessary.
Related ask: bounded wait + SIGKILL fallback in close()
#1370 also requested that SubprocessCLITransport.close() add a bounded wait after terminate() with a SIGKILL fallback. The current close() does await self._process.wait() after terminate(), but inside with suppress(Exception) and without a timeout — meaning if the CLI process ignores SIGTERM (stuck network call, hung hook, etc.), close() blocks indefinitely.
This is the unresolved half of the original architectural concern. It surfaces in our use case as a hard constraint: we keep the CLI subprocess alive across conversation turns. The original per-query connect() / disconnect() pattern hit a cleanup race in an earlier SDK version where disconnect() returned before the subprocess fully exited and the next query's --resume collided with the still-running prior subprocess (failed with "Command failed with exit code 1"). The current close() does await self._process.wait() which may have addressed that specific race, but the unbounded-wait concern from #1370 still applies if SIGTERM is ignored.
Worth resolving alongside the PID exposure since they touch the same code path and serve the same architectural improvement (clean subprocess lifecycle for external owners).
Summary
Request a public
pid(and ideallyprocess) property onSubprocessCLITransportso external orchestrators can manage the CLI subprocess without reaching into private attributes.Why this needs a tracking issue
The request is currently fragmented across multiple artifacts in different repos, with no canonical place to track demand or coordinate resolution:
claude-code/issues, though the code actually lives here inclaude-agent-sdk-python. Hence the cluster of misfiled PRs.pid+processproperties. Correct repo.pidproperty. Correct repo.pidtoSubprocessCLITransportin the wrong repo (the class doesn't exist there).This issue is a canonical home for the request. The two open PRs in this repo (#819, #995) both close it; maintainers can pick one and close the other.
Use case
Distyl.ai operates a coding-agent platform that runs the Claude Code CLI under a per-PID credential proxy. Inbound HTTP from the agent subprocess is intercepted by a local
mitmdumpthat identifies the calling process via kernel-attested PID and injects the right user's credentials. The subprocess never sees real secrets.To register credentials with the proxy, we need the CLI subprocess PID. Today we reach for it like this (paraphrased from our runtime):
Three levels of
getattragainst private attributes, defensively wrapped. Brittle to any internal refactor. A public property would let us writepid = self._sdk_client.transport.pidand remove the defensive scaffolding.The original requester (anthropic-sdk-python#1370) needed it for cancel-cleanup; we need it for credential injection. Both are valid orchestrator concerns the SDK currently makes harder than necessary.
Related ask: bounded wait + SIGKILL fallback in
close()#1370 also requested that
SubprocessCLITransport.close()add a bounded wait afterterminate()with a SIGKILL fallback. The currentclose()doesawait self._process.wait()afterterminate(), but insidewith suppress(Exception)and without a timeout — meaning if the CLI process ignores SIGTERM (stuck network call, hung hook, etc.),close()blocks indefinitely.This is the unresolved half of the original architectural concern. It surfaces in our use case as a hard constraint: we keep the CLI subprocess alive across conversation turns. The original per-query
connect()/disconnect()pattern hit a cleanup race in an earlier SDK version wheredisconnect()returned before the subprocess fully exited and the next query's--resumecollided with the still-running prior subprocess (failed with "Command failed with exit code 1"). The currentclose()doesawait self._process.wait()which may have addressed that specific race, but the unbounded-wait concern from #1370 still applies if SIGTERM is ignored.Worth resolving alongside the PID exposure since they touch the same code path and serve the same architectural improvement (clean subprocess lifecycle for external owners).
Suggested resolution
pidand ideallyprocess.close()as a follow-up, or fold it into the same PR.Happy to test against a release candidate.