macOS Computer Use leaks SkyComputerUseClient turn-ended helpers
Codex Computer Use leaks SkyComputerUseClient turn-ended helper processes on macOS
Summary
Codex Desktop / Computer Use on macOS leaves SkyComputerUseClient helper processes running after turns complete. The leaked helpers include orphaned processes whose parent is PID 1 (launchd) and nested chains of:
SkyComputerUseClient turn-ended --previous-notify <json>
/bin/bash .../codex-notify.sh turn-ended -- SkyComputerUseClient turn-ended <json>
SkyComputerUseClient turn-ended <json>
This accumulates over time and survives normal Codex turns/sessions. The command payload contains turn metadata, so examples here are redacted.
Environment
- Host: macOS 27.0, build 26A5353q, arm64
- Codex.app currently installed: 26.616.32156, build 4157
- Originally observed version from the report: 26.608.12217
codexCLI:codex-cli 0.130.0- Computer Use bundle:
~/.codex/computer-use/Codex Computer Use.app - Computer Use bundle version:
CFBundleShortVersionString=1.0,CFBundleVersion=829 - Service executable:
.../Codex Computer Use.app/Contents/MacOS/SkyComputerUseService - Client executable:
.../SkyComputerUseClient.app/Contents/MacOS/SkyComputerUseClient
Reproduction
- Enable/use Codex Desktop Computer Use or any Codex path that installs the
SkyComputerUseClient turn-endednotifier. - Run several Codex turns or Computer Use actions.
- Check helper counts and parentage:
ps -Ao ppid,comm | awk '/SkyComputerUseClient/{print $1}' | sort | uniq -c | sort -rn
ps -Ao comm | grep -c SkyComputerUseClient
ps -Ao etime,pid,ppid,comm | grep SkyComputerUseClient | sort -r | head
ps -Ao pid,ppid,etime,comm | grep -E 'SkyComputerUseService|MacOS/Codex$'
Expected
After the relevant Codex turn/session ends, all per-turn SkyComputerUseClient helpers should exit. If the service exits, it should terminate and/or reap all children it spawned. A broken --previous-notify command should not leave the client process alive indefinitely.
Actual
Helpers remain alive for hours/days. On this machine, a previous run observed 1,422 simultaneous SkyComputerUseClient processes. In the current reproduction before cleanup:
ps -Ao comm | grep -c SkyComputerUseClientreturned22.ps -Ao ppid,comm | awk '/SkyComputerUseClient/{print $1}' ...showed7clients parented by PID1.- The oldest current helpers were over
02:13:00old. - The service process was alive as a child of Codex:
/Applications/Codex.app/Contents/MacOS/Codex
~/.codex/computer-use/Codex Computer Use.app/Contents/MacOS/SkyComputerUseService
Unified logs showed turn-end events with no active lock-screen threads while helper processes remained:
SkyComputerUseService: Received lock-screen turn end ... activeThreadCount=0 autoUnlockedThreadCount=0
Evidence
Info.plistidentifies the service ascom.openai.sky.CUAServiceand the nested client ascom.openai.sky.CUAService.cli.- Entitlements show both service and client share the
2DC432GLL2.com.openai.sky.CUAServiceapp group. - The bundled Computer Use plugin launches the MCP server via:
{
"command": "./Codex Computer Use.app/Contents/SharedSupport/SkyComputerUseClient.app/Contents/MacOS/SkyComputerUseClient",
"args": ["mcp"]
}
- The leaked process command lines were
turn-endednotifier invocations, not active UI interaction commands. - The local
~/.codex/config.tomlhad been rewritten to:
notify = [ "SkyComputerUseClient", "turn-ended", "--previous-notify", "[...codex-notify.sh..., ...SkyComputerUseClient..., turn-ended]" ]
This creates a self-wrapped notifier chain when an existing wrapper already preserves the original SkyComputerUseClient turn-ended notifier.
Probable root cause
There are two lifecycle gaps:
SkyComputerUseClient turn-endedcan block indefinitely after spawning/invoking the previous notifier chain. Its parent exits or detaches, leaving the helper reparented tolaunchd.- The Computer Use service / installer wraps the existing Codex notify command without detecting that the previous notifier chain already includes
SkyComputerUseClient turn-ended, creating a nested self-wrapper. The service also does not reap staleturn-endedhelpers after turn completion.
Local mitigation installed
I installed a local, age-filtered mitigation:
- Reset
~/.codex/config.tomlto call the local notify wrapper first, then the originalSkyComputerUseClient turn-ended. - Hardened
~/.config/dev-knowledge/hooks/codex-notify.sh: - strips recursive
SkyComputerUseClient --previous-notifychains, - runs the original notifier with a bounded timeout (
DK_CODEX_NOTIFY_ORIGINAL_TIMEOUT_SECONDS, default20), - logs timeout/recursion warnings explicitly.
- Added
/Users/jeremy/.local/bin/codex-computer-use-reaper. - Default threshold:
3600seconds. - Matches only the exact
SkyComputerUseClientexecutable path. - Redacts turn JSON in logs.
- Added and loaded LaunchAgent:
/Users/jeremy/Library/LaunchAgents/com.jeremy.codex-computer-use-reaper.plist- Runs at load and every 300 seconds.
Verification after mitigation:
- Dry-run found
16helpers,14older than 3600 seconds,2skipped as fresh. - Real run reaped
14stale helpers and left the2fresh helpers untouched. launchctl print gui/501/com.jeremy.codex-computer-use-reapersucceeds and reports interval300seconds.- Wrapper timeout test exits
124when a notifier exceeds the configured timeout; pass-through notifier test exits0.
Requested upstream fix
- Make
SkyComputerUseClient turn-endedalways exit after notifying the service and/or invoking--previous-notify, with a bounded timeout for the previous notifier. - Detect and reject recursive
--previous-notifychains that already includeSkyComputerUseClient turn-ended. - Ensure
SkyComputerUseServicetracks all spawned helper PIDs and tears them down on turn end/service exit. - Add a stale-helper guard in the service: cap concurrent helpers and terminate old
turn-endedhelpers safely.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗