Skip to content

fix: exit process when ACP connection closes#530

Merged
benbrandt merged 3 commits intoagentclientprotocol:mainfrom
Sway-Chan:fix/exit-on-connection-close
Apr 13, 2026
Merged

fix: exit process when ACP connection closes#530
benbrandt merged 3 commits intoagentclientprotocol:mainfrom
Sway-Chan:fix/exit-on-connection-close

Conversation

@Sway-Chan
Copy link
Copy Markdown
Contributor

Summary

  • Return AgentSideConnection from runAcp() instead of discarding it
  • Listen for connection.closed and call process.exit(0) on resolution
  • Fixes orphan process accumulation in oneshot mode (e.g. via ACPX)

Problem

When used in oneshot mode, claude-agent-acp does not exit after the client closes the stdin pipe. process.stdin.resume() keeps the Node.js event loop alive indefinitely. Over time, orphan processes accumulate on the host (~97MB RSS each), eventually exhausting system resources.

Root cause

runAcp() creates an AgentSideConnection but discards the reference. The Connection.#receive() loop detects stdin EOF and fires abortController.abort(), resolving connection.closed — but no code listens for it to trigger process.exit().

Fix

  1. acp-agent.ts: runAcp() now returns the AgentSideConnection instance
  2. index.ts: Awaits connection.closed and calls process.exit(0)

Impact

  • Oneshot sessions: Process now exits cleanly when the client closes stdin (EOF)
  • Persistent sessions: Unaffected — the client keeps stdin open, so connection.closed does not fire until explicit disconnect

Test plan

  • Verified oneshot: process exits within 1s after stdin EOF
  • Verified persistent: process remains alive while stdin is open
  • Measured idle RSS: ~97MB → freed on exit
  • Tested with ACPX runtime (OpenClaw gateway) in production

🤖 Generated with Claude Code

In oneshot mode (e.g. via ACPX), the claude-agent-acp process does not
exit after the client closes the stdin pipe. `process.stdin.resume()`
keeps the Node.js event loop alive indefinitely, causing orphan process
accumulation on the host.

Root cause: `runAcp()` discards the `AgentSideConnection` instance, so
nothing listens for connection closure to trigger `process.exit()`.

Fix: return the connection from `runAcp()` and call `process.exit(0)`
when `connection.closed` resolves (i.e. when stdin reaches EOF).

Persistent sessions are unaffected — the client keeps stdin open, so
`connection.closed` does not fire until the client explicitly
disconnects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Sway-Chan Sway-Chan closed this Apr 8, 2026
@Sway-Chan Sway-Chan reopened this Apr 8, 2026
Copy link
Copy Markdown
Member

@benbrandt benbrandt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@benbrandt benbrandt enabled auto-merge (squash) April 13, 2026 16:40
@benbrandt benbrandt merged commit 5c81e99 into agentclientprotocol:main Apr 13, 2026
1 check passed
benbrandt added a commit that referenced this pull request Apr 13, 2026
Make cancellation a no-op for unknown sessions, close each
session query during disposal, and run the same cleanup path on
SIGINT and SIGTERM in CLI mode.

Follow up to #530
benbrandt added a commit that referenced this pull request Apr 13, 2026
Make cancellation a no-op for unknown sessions, close each
session query during disposal, and run the same cleanup path on
SIGINT and SIGTERM in CLI mode.

Follow up to #530
benbrandt pushed a commit that referenced this pull request Apr 13, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.27.0](v0.26.0...v0.27.0)
(2026-04-13)


### Features

* allow clients to opt into receiving raw SDK messages
([#527](#527))
([403a668](403a668))
* Update to claude-agent-sdk 0.2.104
([#537](#537))
([6811943](6811943))


### Bug Fixes

* Allow auto mode after plan mode and send description for auto mode
([#528](#528))
([fb9aced](fb9aced))
* Better remote check for auth methods
([#538](#538))
([93f58c0](93f58c0))
* better shutdown logic
([#543](#543))
([9fb631f](9fb631f))
* exit process when ACP connection closes
([#530](#530))
([5c81e99](5c81e99))
* guard tool info rendering when tool_use input is undefined
([#536](#536))
([d627b8c](d627b8c))
* Remove backup auth check from new session
([#544](#544))
([32b16c1](32b16c1))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: acp-release-bot[bot] <246668977+acp-release-bot[bot]@users.noreply.github.com>
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.

2 participants