github b-nnett/codex-plusplus v2.0.0
Codex++ 2.0.0

3 hours ago

Codex++ 2.0 is a new implementation for the ChatGPT desktop app (com.openai.codex): a signed macOS menu-bar helper that stages, probes and atomically installs a patched copy of the app, built and signed locally with your own Developer ID. It shares no code with Codex++ 1.x (the Node-based tweak system), whose source stays on the legacy-1.x branch and whose tags and releases are unchanged. 1.x tweaks are not loaded by 2.0; extensions use the contract in the README.

Upgrading from 1.x: quit ChatGPT, run codexplusplus uninstall (add --purge to also delete 1.x tweaks and data), then build and install 2.0. 2.0 only patches an app that still carries OpenAI's signature, so it refuses an app 1.x has modified. 1.x's background update check will see 2.0 as its latest release and fail before changing anything, because 2.0 is not a 1.x package.

  • Initial source release of the Codex++ macOS menu bar helper and renderer extension host.
  • Exact-build patch recipes, authenticated update handoff, atomic rollback, native Settings integration, Appshot compatibility, AutoFill, bookmarks, Better Sidebar, and Focus Mode.
  • Main-process extension injection without an externally reachable DevTools endpoint.
  • Extension polling sends code to a window only when it changes; steady-state polls are a small status probe. Polls no longer overlap, a hung window cannot queue calls, and diagnostics are rewritten only on change or every five seconds.
  • Patch v41 (v37–v40 unreleased): an optional better-sidebar contract discovered by code shape replaces minified export names; the browser menu adapter tolerates an upstream frame option.
  • Extensions can report non-fatal warnings with api.warn.
  • Appshot runtime warmup waits 15 seconds after launch instead of starting while the first window loads, and its vendor signature checks no longer block the main process. A capture requested earlier starts the runtime itself. scripts/bench-startup.py compares cold-launch time to interactivity of the patched and original apps.
  • The helper menu no longer pops open on every ChatGPT launch; the bootstrap's background open -g reopen is ignored unless it activates the helper.
  • Startup fast path (optional AST adapter, codexpp-startup-discovery.json reports what matched): ChatGPT sign-ins build the Statsig client from the last bootstrap payload for the same identity (kept in IndexedDB) instead of holding the whole window behind a spinner until OpenAI's bootstrap request returns, then apply the fresh payload when it arrives; Statsig's cached values end its async loading state; the dictation sound cues are no longer preloaded at launch. A first launch, a different account or app version, or an unrecognised build behaves exactly as before.
  • The Dock icon preference is applied 3 s after launch instead of before the first window exists (about 65 ms earlier window).
  • Hidden prewarmed windows (new Page window, avatar overlay, hotkey window, detached window) are created when their feature is first opened instead of 3–13 s after launch: about half the CPU and 45% less memory 25 s after launch. bench-startup.py --steady N measures CPU and memory N seconds after launch and --idle A:B the idle CPU between two points, and traced launches list each window's route, TanStack query waterfall, running animations and console-error sources; trace-report.py reports jank in the 5 s after interactive.
  • The loading shimmer ("Thinking", "Working for …") runs on the compositor: the label is drawn once and a highlight copy slides under a moving window, with the same path, timing and colours, instead of repainting the text on every step. A visible shimmer costs about half the CPU (26.8% → 13.2% of a core, median of three runs each). Labels with more than plain text keep the original shimmer. The demoShimmer experiment shows a fixed label for A/B tests. It pauses while the window is in the background.
  • With the side panel open, the chat column no longer jitters while the window resizes. The shell measured its width with a ResizeObserver, which runs after layout, and the panel width it drives was written on the next frame, so the chat column took the whole change for one frame and snapped back. Observers of window-wide elements now get their new size from the window's resize event, before the frame is laid out. In a scripted resize the chat/panel divider jumped backwards 132 times (stock) and now does not move at all.
  • Window resizing no longer restyles and relays out the whole window at every breakpoint. ChatGPT's main stylesheet has 47 width media queries, and each time the window crossed one Chromium rebuilt the sheet, reset every @font-face, @property and @keyframes rule and recomputed all of the window's styles, about 50 times in a 6 s resize of a long thread. Width-only media rules now run as container queries on <html>, which is always exactly the viewport, so a breakpoint only restyles what it styles. In that resize, style work fell from 971 to 409 ms, layout from 889 to 579 ms and main-thread busy time from 4.2 to 3.4 s; frames longer than 16.7 ms went from 62 (1.9 s in all) to 18 (0.5 s), and frames longer than 33 ms from 34 to 3.
  • Resizing the window with the side-panel browser open no longer freezes it. The panel's browser reports its bounds on every frame, and each report rebuilt ChatGPT's whole application menu: 1.6 s of main-process work in a 12 s hand resize, ending in a 0.9 s garbage collection during which nothing was drawn. A burst of reports now rebuilds the menu once at the start and once 250 ms later. In the same hand resize the main process went from 3.5 s busy to 1.5 s, the longest garbage collection from 448 ms to 6 ms, the longest gap between frames from 872 ms to 68 ms (seven over 100 ms before, none after) and the frame rate from 85 to 113 per second.
  • A turn no longer sets off repeated MCP inventory refetches. Each MCP server of a new thread (including the hidden thread that predicts the next prompt after every turn) reported ready separately, and each report refetched the host's MCP inventory, which starts every MCP server again; a short turn cost four extra inventory requests and about 24 node process launches. Ready reports now collapse into one trailing refetch per thread, skipped when the inventory was fetched in the last minute. scripts/process-sampler.py records CPU, spawned processes and memory of ChatGPT's whole process tree while it works.
  • Personal accounts no longer boot a hidden, signed-in chatgpt.com checkout page at launch (about 250–350 MB); the upgrade and credit pages load when opened. bench-startup.py --steady also reports the true memory footprint (macOS footprint), and traces list every web contents and iframe with its process, query result sizes and the JS heap.
  • A focused, untouched ChatGPT window no longer spends about 12% of a CPU core redrawing its blinking text cursor: the caret blinks for 5 s after activity, then stays steady (steady with Reduce Motion).
  • Extension sync is event-driven: settings and extension file changes and window loads sync at once, and an idle app is checked every 4 s instead of every second (two scripts per window per second before).
  • The helper menu shows how many startup speed-ups matched the installed ChatGPT build and lists any that did not, so a ChatGPT update that breaks one is visible.
  • Benchmark experiments for development builds only (CODEXPP_EXPERIMENTS=1 ./scripts/build-app.sh), read from Diagnostics/experiments.json: scripted window resizes and side-panel toggles, Chromium traces of them or of a hand-driven session, script probes, injected stylesheets, renderer V8 flags, a forced opaque window surface and a fixed shimmer label. Release bootstraps contain none of this code and never read the file. The Node compile cache for the main-process bundles is always on.
  • scripts/evidence-video.py films stock and patched ChatGPT under identical conditions (window resize, side-panel toggles, idle cursor, shimmer) with a live CPU readout of the whole process tree and renders labelled side-by-sides; process-sampler.py --bundle samples the untouched original bundle.
  • Release tooling: check.sh runs the startup adapter and tracer tests, check-release.sh no longer needs ripgrep, and release-source.sh archives the repository root.
  • Codex++ updates itself from GitHub releases: a daily check verifies an SSH-signed release manifest against the release key compiled into the helper, downloads and verifies the source tarball, builds and signs it locally with the pinned Developer ID in the background, and offers Restart to Update. The staged helper swaps itself in atomically and rolls back if it does not start; the menu then offers to repatch ChatGPT with the new revision. release-source.sh writes and signs the schema-2 manifest, and a release workflow publishes a drafted release only when its rebuilt tarball and signature match.
  • Audit fixes: release builds carry no startup tracer, compile cache or diagnostic edits; code Codex++ loads lives inside the signed patched app; injected scripts no longer run with user activation; the cached shell environment keeps only allow-listed variables; the staged copy is re-authenticated before re-signing and the patched app must carry the pinned signer; the swap waits for ChatGPT's own processes to exit and stale transactions no longer block repatching; an unreadable settings file stops every extension.

Don't miss a new codex-plusplus release

NewReleases is sending notifications on new releases.