Chronicle can drive replayd to 100% CPU and make CleanShot / ScreenCaptureKit hang on macOS 26.0

Open 💬 4 comments Opened Apr 30, 2026 by KaishuShito

What issue are you seeing?

On one Mac, enabling Codex Chronicle appears to make macOS replayd spin at roughly 99-100% CPU. While this is happening, CleanShot X becomes very slow and ScreenCaptureKit calls can hang or time out. Disabling Chronicle and killing the stale Chronicle / replayd processes immediately restores CleanShot and ScreenCaptureKit behavior.

This looks like a Chronicle + macOS ScreenCaptureKit / replayd interaction. CleanShot seems to be affected because it shares the same macOS screen capture service, not necessarily because CleanShot is the root cause.

Environment

Main Mac where the issue reproduces:

macOS: 26.0 (25A354)
Architecture: arm64
Codex Desktop: 26.422.71525 (bundle version 2210)
Codex Chronicle binary: /Applications/Codex.app/Contents/Resources/codex_chronicle
codex_chronicle sha256: 6a599d41e5b2f4e5efd392526f43a26eff8df5971fe741e237da8247b1aa30e1
codex_chronicle mtime/size: Apr 29 10:40:18 2026, 4427728 bytes
CleanShot X: 4.8.8
Current display setup: built-in Color LCD + external P27FBA-RAGL 1920x1080 @ 100Hz

Codex app entitlements include:

com.apple.security.device.audio-input = true

Comparison Mac mini where Chronicle and CleanShot coexist normally:

macOS: 26.2 (25C56)
Codex Desktop: 26.422.62136
Codex CLI: codex-cli 0.124.0
CleanShot X: 4.8.8
Display: single external P27FBA-RAGL, 1920x1080 @ 100Hz
Observed load: codex_chronicle ~0.5-2.6%, replayd ~0.0-0.7%, CleanShot X ~0.0%
Chronicle latest.jpg stayed fresh on that machine

Symptoms observed on the affected Mac

When Chronicle is enabled:

  • codex_chronicle starts and spawns a --list-displays-child process.
  • replayd rises to approximately 99-100% CPU.
  • CleanShot X becomes noticeably slow.
  • Chronicle does not produce a fresh latest.jpg under $TMPDIR/chronicle/screen_recording/.
  • Chronicle-generated memory summaries stopped updating. The latest local summary I found was from 2026-04-22 23:17 JST.
  • A minimal ScreenCaptureKit test that calls SCShareableContent can hang / time out while the system is in this state.

When Chronicle is disabled in Codex Settings and stale processes are killed:

  • replayd drops back to roughly 0.0-0.1% CPU.
  • CleanShot X becomes fast again.
  • The same minimal ScreenCaptureKit test succeeds quickly. One successful run completed in 0.027s and returned displays 1, windows 25.

At the time of filing, Chronicle is intentionally disabled on this Mac as a workaround. Current process state is stable:

coreaudiod: 0.0% CPU
CleanShot X: 0.0% CPU
replayd: 0.0% CPU
no active codex_chronicle process

Reproduction / isolation steps already tried

  1. Enable Chronicle in Codex Desktop.
  2. Observe codex_chronicle start.
  3. Observe replayd climbing to ~99-100% CPU.
  4. Try CleanShot X capture; CleanShot becomes slow.
  5. Check Chronicle temp capture directory; latest.jpg is missing or stale.
  6. Run a small ScreenCaptureKit / SCShareableContent test; it can hang or time out.
  7. Turn Chronicle off from Codex Settings.
  8. Kill stale codex_chronicle and restart/kill replayd if needed.
  9. Observe CleanShot and ScreenCaptureKit recover immediately.

I also tried removing the external display and leaving only the built-in display. Chronicle still triggered the bad state, so this does not appear to be caused solely by multi-display capture. However, multi-display capture may still be a contributing factor or amplifier.

Expected behavior

Chronicle should not put replayd into sustained 99-100% CPU, and it should not make other ScreenCaptureKit-based apps such as CleanShot X unusable.

If Chronicle cannot acquire screen capture cleanly, it should fail or back off rather than leaving replayd saturated and failing to write fresh capture frames.

Actual behavior

Chronicle appears to enter a bad capture state where replayd stays saturated, Chronicle capture output is not fresh, and other screen capture apps become slow until Chronicle is disabled and stale processes are cleared.

Related issues

This seems related to several recent Chronicle / macOS capture issues, but I did not find an exact CleanShot + replayd report:

  • #19134: recurring macOS private-window-picker / screen-and-audio prompt after Allow
  • #19126: Chronicle triggering high coreaudiod CPU with Rogue Amoeba ARK / SoundSource
  • #19516: orphaned codex_chronicle after killed app causes lock-wait loop and high CPU
  • #19341: request for selected-display capture and pause/resume controls

The lifecycle aspect in #19516 is especially plausible here because this affected Mac had a Codex app freeze during an update before the issue was noticed.

Workaround

Keep Chronicle disabled on the affected Mac. If it has already entered the bad state, disable Chronicle, then stop stale helpers:

pkill -f '/Applications/Codex.app/Contents/Resources/codex_chronicle'
killall replayd

After that, CleanShot and ScreenCaptureKit recover.

Additional notes

The comparison with the Mac mini suggests that high refresh rate alone is probably not the whole explanation: the Mac mini is using the same external display at 100Hz and runs Chronicle + CleanShot normally. The affected Mac is still on macOS 26.0, while the healthy Mac mini is on macOS 26.2, so this may involve a macOS ScreenCaptureKit / replayd bug that newer macOS builds handle better.

View original on GitHub ↗

4 Comments

KaishuShito · 3 months ago

Follow-up with a narrowed repro and likely fix direction from the same affected Mac.

Environment:

macOS: 26.4.1 (25E253), arm64
Codex Desktop: 26.506.31421
Codex bundle version: 2620
prod codex_chronicle sha256:
dd7aa739aad2477cf8798d29e38b4588790bb5c5cf13402dbd18c9780ddf115a

This is still the latest prod appcast entry I see. The installed helper matches the official prod zip helper. The beta helper for 26.506.31421 / bundle 2619 also fails the same way.

Direct child request:

printf '%s\n' '{"request":"list_displays"}' \
  | /Applications/Codex.app/Contents/Resources/codex_chronicle --screen-capture-child

Result:

rc=124
ScreenCaptureKit child exceeded 5000ms timeout; forcing exit

This also reproduces when:

  • running from a /tmp copy of the helper
  • running with a nearly empty environment
  • running an ad-hoc re-signed /tmp copy
  • after restarting replayd

TCC/unified logs show TCC Allow; this does not look like a permission denial.

I sampled the helper while it was stuck:

codex_chronicle::screen::child::run_screen_capture_child
  codex_chronicle::screen::macos::get_displays_direct
    screencapturekit::shareable_content::SCShareableContent::get
      screencapturekit::utils::completion::SyncCompletion<T>::wait
        _pthread_cond_wait

The timeout thread was sleeping in:

codex_chronicle::screen::subprocess::arm_screen_capture_subprocess_timeout

The important narrowed finding: default SCShareableContent enumeration hangs on this machine, but filtered enumeration succeeds.

Default API:

SCShareableContent.getWithCompletionHandler { ... }

Result:

timeout default

Equivalent Rust screencapturekit = 1.5.4 default call also hangs:

SCShareableContent::get()

Filtered API:

SCShareableContent.getExcludingDesktopWindows(false, onScreenWindowsOnly: true) { ... }

Result:

ok 0.038s displays 2 windows 52 apps 12

onScreenWindowsOnly: true appears to be the key option:

getExcludingDesktopWindows(true, onScreenWindowsOnly: false)
timeout

getExcludingDesktopWindows(false, onScreenWindowsOnly: true)
ok 0.038s displays 2 windows 52 apps 12

Suggested fix direction for Chronicle's display inventory path:

let content = SCShareableContent::create()
    .with_on_screen_windows_only(true)
    .with_exclude_desktop_windows(false)
    .get()?;

I used exclude_desktop_windows(false) because it still returns the full display list locally; the important part appears to be on_screen_windows_only(true). Since the Chronicle list_displays path only needs display inventory, this should avoid the local replayd hang caused by enumerating all/off-screen windows.

With Chronicle disabled locally:

chronicle = false

there is no active codex_chronicle process, replayd returns to idle, and filtered Swift/Rust SCShareableContent probes succeed.

Korkyzer · 3 months ago

Confirming this on a third machine with identical Codex / macOS versions.

Environment

macOS: 26.2 (25C56), arm64 (M5)
Codex Desktop: 26.506.31421
Codex bundle version: 2620

Quantified replayd saturation

While Chronicle was enabled, replayd was accepting short-lived client connections at a steady rate. Counted via:

/usr/bin/log show --last 2m --predicate 'process == "replayd" AND eventMessage CONTAINS "accepted client connection"' | grep -c "PID:"

Result: ~70 distinct client PIDs in 2 minutes (range observed: 4097 -> 4395 over 120s). Each PID was a codex_chronicle --screen-capture-child worker spawned by the parent codex_chronicle daemon (PPID match confirmed via ps -axo pid,ppid,command). Each child died within milliseconds, consistent with the documented 5000ms ScreenCaptureKit timeout hitting on the default SCShareableContent::get() call described by @KaishuShito above.

System-wide impact (beyond CleanShot)

The saturation breaks the entire macOS screen capture pipeline, not just third-party tools:

| Path | Behavior |
|---|---|
| cmd+shift+3 / cmd+shift+4 | freezes, no file produced |
| cmd+shift+5 (screenshot toolbar) | freezes |
| Shottr | freezes mid-capture |
| /usr/sbin/screencapture -x /tmp/x.png (CLI) | fails with could not create image from display |

After codex features disable chronicle + killing the parent codex_chronicle PID, all four paths recovered immediately, no reboot required.

Reboots do not help

Worth flagging for anyone landing here: rebooting does not fix this. Codex auto-launches via macOS modern login items, codex_chronicle respawns within seconds of login, replayd is saturated again, and the system looks broken from a fresh boot. The only durable fix is the config toggle.

Workaround confirmed durable

/Applications/Codex.app/Contents/Resources/codex features disable chronicle

This writes features.chronicle = false to ~/.codex/config.toml. After quitting and relaunching Codex.app, the codex_chronicle daemon no longer spawns at all. replayd returns to 0 client connections / 10s and all screenshot paths work normally. Codex itself (chat, plan mode, app-server, MCP servers, computer_use, browser_use) keeps functioning fully.

Adding this here so future searchers find the systemic impact (not just CleanShot) and the durability of the workaround across restarts.

jjhuang2023 · 2 months ago

Adding another data point from a different machine, because it looks like the same Chronicle / ScreenCaptureKit / replayd failure mode, but with low aggregate CPU and Chrome window capture failures.

Environment:

macOS: 26.5 (25F71), arm64
Codex Desktop: 26.527.31326 (bundle build 3390)
Chrome: 148.0.7778.181
Display setup: two external 4K displays
Chronicle binary: /Applications/Codex.app/Contents/Resources/codex_chronicle

Observed symptoms:

  • macOS screenshot/window capture would intermittently hang or fail; the whole desktop could become noticeably stuck even though total CPU was reported under ~15%.
  • Logs during the failure included:
ScreenCaptureKit [ERROR] +[SCShareableContent getWindowForWindowId:]:267 getWindowForWindowId timed out
screencapture: capture error could not create image from window
WindowServer: Screenshots via streams are inefficient and should be avoided. Please use the SLSScreenshot SPI.
  • In one 5-minute window there were 245 WindowServer "Screenshots via streams..." messages.
  • replayd logged accepted client connection PID: 6862; that PID was /Applications/Codex.app/Contents/Resources/codex_chronicle --screen-capture-child.
  • Sending TERM stopped the parent codex_chronicle process, but the --screen-capture-child remained orphaned and had to be killed separately.
  • After killing the Chronicle screen-capture child, screenshot behavior recovered and the previously affected Chrome tab could be captured without refreshing it.

Window-specific behavior:

  • A normal Chrome window captured successfully with screencapture -x -l <window_id> in about 0.23s and produced a valid PNG.
  • A different complex/GPU-composited Chrome page failed in about 1s with the same getWindowForWindowId timed out / could not create image from window errors.
  • This makes Chronicle look like a strong amplifier of a shared macOS capture-service failure mode: not necessarily the only trigger, but enough to push replayd / ScreenCaptureKit into a bad state where unrelated screenshot tools also degrade.

Possible product-level fixes worth considering:

  1. Use a single local capture broker that owns ScreenCaptureKit / replayd access and multiplexes frames to Chronicle, computer-use, and explicit screenshot features, instead of allowing multiple independent capture loops.
  2. Add adaptive backoff when WindowServer emits repeated stream-screenshot warnings, SCShareableContent times out, or frame freshness stalls. Back off FPS/resolution or pause capture instead of retrying aggressively.
  3. Add a watchdog so the parent process reaps or stops orphaned codex_chronicle --screen-capture-child processes and resets capture state when the parent exits or frame output goes stale.
  4. For explicit screenshots, use a fallback ladder: full-screen capture plus crop, browser/CDP screenshot for Chrome pages, then window-ID capture, rather than repeatedly using the same ScreenCaptureKit path once it starts timing out.
  5. Expose a local pause/reset control for Chronicle capture so users can recover the capture stack without quitting Codex or manually killing helper processes.

I can provide additional redacted log snippets if they would help isolate the failure mode.

MumuTW · 2 months ago

Adding an independent datapoint on a newer Codex Desktop build where the same Chronicle / ScreenCapture path appears to fan out into a tccd -> syspolicyd / securityd / trustd / logd log storm.

Environment:

Hardware: MacBook Air, Mac15,12, Apple M3, 8 cores, 16 GB RAM
macOS: 26.5.1 (25F80), Darwin 25.5.0, arm64
Codex Desktop: 26.602.71036 (bundle build 3685)
Codex bundle id: com.openai.codex
TeamIdentifier: 2DC432GLL2
Chronicle: was enabled during the spike; later disabled by the user
Screen Recording / Accessibility permissions: granted to Codex

Observed symptoms while Chronicle was enabled:

load average around: 8.24 / 7.54 / 7.13
CPU snapshot included:
  syspolicyd up to ~98% CPU
  mediaanalysisd up to ~87% CPU
  trustd around ~30% CPU in one sample
  WindowServer around ~30% CPU
  logd had earlier been observed around ~49% CPU

The most useful additional signal is that the apparent hot path was not only replayd CPU. The logs show repeated ScreenCapture TCC checks for Codex/Chronicle, followed by repeated static code / trust evaluation and syspolicy ticket lookup.

Sanitized tccd attribution chain from log show --style compact --info --debug --predicate 'process == "tccd"':

service="kTCCServiceScreenCapture"
requesting={TCCDProcess: identifier=com.apple.replayd, pid=704, binary_path=/usr/libexec/replayd}
accessing={TCCDProcess: identifier=codex_chronicle-..., binary_path=/Applications/Codex.app/Contents/Resources/codex_chronicle}
responsible={TCCDProcess: identifier=com.openai.codex, pid=2977, binary_path=$TMPDIR/.../com.openai.codex.code_sign_clone/.../Codex.app.bundle/Contents/MacOS/Codex}

Repeated error from tccd:

Failed to create LSApplicationRecord for file://$TMPDIR/.../com.openai.codex.code_sign_clone/.../Codex.app.bundle/: OSStatus error -10811

Counts captured from local logs over the preceding 30 minutes:

# tccd events containing com.openai.codex
total_codex_tccd_events: 15778
screen_capture_events: 333
failed_ls_application_record: 2900
attribution_chain_events: 943
top pids included: com.openai.codex main process, replayd, WindowServer, coreaudiod, tccd, codex_chronicle

# syspolicyd events
total_syspolicyd_events: 532394
requester_pids: 435 (system tccd) = 427, 672 (user tccd) = 47
top subsystems:
  com.apple.CFNetwork: 108448
  com.apple.network: 95868
  com.apple.syspolicy.exec: 43160
  com.apple.syspolicy: 26480

top messages:
  SecTrustCopyAppleTrustAnchors: 131824
  SecKeyVerifySignature: 59955
  SecTrustEvaluateIfNecessary: 45321
  Couldn't find a cached target during malware scan: 14562
  failed to call driver: 0x3: 14535
  looking up ticket / cloudkit record fetch / cache info: 5189 each

Process state after disabling Chronicle:

pgrep -alf 'codex_chronicle|Chronicle' -> no codex_chronicle process remains

There were also many MCP/Node helper processes in this session, but the direct evidence for this spike points to the ScreenCapture permission path:

Codex/Chronicle -> replayd / WindowServer ScreenCapture check -> tccd -> repeated Codex code_sign_clone static code validation -> syspolicyd/securityd/trustd/logd pressure

This may be related to the broader syspolicyd reports in #25882 and process-lifecycle reports in #25744, but this datapoint is specifically the Chronicle ScreenCapture/TCC path and the repeated com.openai.codex.code_sign_clone LSApplicationRecord/static-code validation loop.