From 6784f72f60633939de4d48524fb74d1c5340d306 Mon Sep 17 00:00:00 2001 From: Alexander Chen Date: Tue, 15 Sep 2026 15:35:09 -0400 Subject: [PATCH] Shorten README and lead with agent-assisted setup --- README.md | 141 ++++++++++----------------------------------- docs/reference.md | 142 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 112 deletions(-) create mode 100644 docs/reference.md diff --git a/README.md b/README.md index 0c4db8e..7fa0bf5 100644 --- a/README.md +++ b/README.md @@ -2,130 +2,47 @@ Codex Update Helper moon and update arrow icon -Keep the Codex desktop app current on macOS, even when it stays open for days. +Keep Codex up to date overnight, even when you leave it open for days. -Codex already downloads and verifies its own updates with Sparkle. This helper finishes staged updates during **2–3 a.m. Eastern**, asks Codex to quit gracefully, waits for Sparkle to install, and reopens Codex only if it was open before. +## Set up with Codex -> Unofficial community utility. Not affiliated with or endorsed by OpenAI. +Copy this into your Codex agent on the Mac you want to set up: -## Install - -From the repository on macOS (Xcode Command Line Tools are required to build): - -```bash -zsh scripts/install-local.sh -open "$HOME/Applications/Codex Update Helper.app" +```text +Install and set up https://github.com/exprmntl/codex-update-helper on this Mac. +Read the repository instructions and docs/reference.md, check prerequisites, +and use scripts/install-local.sh. Preserve any existing settings; for a new +installation, use the defaults: updates between 2–3 a.m. America/New_York, +only when no local tasks are active and the Mac has been idle for 15 minutes, +retry every 15 minutes, and reopen Codex if it was open before. + +Verify the installed service, saved settings, and Accessibility permission +from a standalone background process. Complete everything you can, then give +me clear steps only for anything I must do myself, such as macOS consent. +Don't quit or restart Codex to test the setup while I'm working. ``` -Enable **Codex Update Helper** once in **System Settings → Privacy & Security → Accessibility**. If it is not listed, use **+** and select the app in your home folder's Applications directory. The helper defers before requesting a quit until this permission is available. Rebuilding an ad-hoc signed helper may require re-enabling its permission. +Requires macOS, Codex at `/Applications/ChatGPT.app`, and Xcode Command Line Tools to build. Accessibility permission lets the helper handle Codex’s quit confirmation automatically. -The local installer backs up and replaces the existing `dev.exprmntl.codex-update-helper` LaunchAgent, including an older Homebrew installation. It installs a self-contained app under `~/Applications`; no checkout is needed at runtime. Existing Homebrew files are preserved. Do not run `brew services restart codex-update-helper` afterward: that restores the older Homebrew service configuration. Use the local installer to reinstall this version. +## How it works -By default, the service attempts updates every 15 minutes between **02:00 inclusive and 03:00 exclusive in `America/New_York`**, following daylight saving time independently of the Mac's timezone. It also requires 15 minutes of keyboard/mouse inactivity. A busy Mac is retried during that hour, then the following night. If the Mac sleeps through the window, the helper skips the daytime wake-up; it does not wake the Mac. The spring-forward date has no 2 a.m. hour, so that night's default update window is skipped. +Codex downloads updates through its built-in updater, Sparkle. This helper enables automatic downloads and finishes waiting updates during your chosen window: it verifies the app signatures, asks Codex to quit gracefully, lets Sparkle install, and reopens Codex. -Codex's own quit dialog distinguishes active local tasks and worktrees still starting from merely having scheduled tasks enabled. By default, the helper accepts only the exact English scheduled-tasks-only warning. It cancels a recognized quit dialog with any other warning, including active work, and never clicks an unrelated dialog. Unknown/localized dialog structures are left alone and time out without a forced quit. +By default, it waits while local tasks are active. Having scheduled tasks enabled alone won’t block a restart. Your Mac must be awake during the window; the helper doesn’t wake it or catch up during the day. Automatic quit confirmation currently supports known English dialogs. ## Settings -Open **Codex Update Helper** from your home folder's Applications directory, or run `./bin/codex-update-helper settings`. The settings window lets you change the schedule and restart behavior. Settings are stored in `~/Library/Application Support/Codex Update Helper/settings.plist` and survive reinstalls. The service reads them each minute; changes take effect on the next check without reinstalling or restarting the service. +Open **Codex Update Helper** in your home folder’s **Applications** directory. Use the time pickers, timezone dropdown, and other controls, then **Save**. Changes apply automatically and survive reinstalls; **Restore defaults** brings back these choices. -Use the native time pickers for start/end times, the searchable timezone dropdown, and the idle/retry menus. The idle menu disables automatically when you choose to restart during active work. **Restore defaults** fills in the default choices; **Save** applies them. **Cancel** leaves saved settings unchanged. - -| Setting | Default | Behavior | +| Setting | Default | What you can change | | --- | --- | --- | -| `start-time` | `02:00` | Start of the update window, in 24-hour HH:MM format. | -| `end-time` | `03:00` | End of the window, exclusive. Windows may cross midnight; start and end must differ. | -| `timezone` | `America/New_York` | Named timezone, including daylight saving changes. | -| `idle-minutes` | `15` | Keyboard/mouse inactivity required for `idle-only`; `0` disables this extra check. | -| `retry-minutes` | `15` | Time between update attempts within the window. | -| `restart-policy` | `idle-only` | Wait for no active local tasks or worktrees being created. `always` permits interrupting active work and ignores keyboard/mouse inactivity. | -| `reopen` | `true` | Reopen Codex if it was open before the update; `false` leaves it closed. | - -The **always** policy still uses a graceful quit and Sparkle's installer. It approves known warnings about active local tasks and worktrees being created, which can interrupt or lose that work. It does not force-kill a hung app, bypass signature checks, or approve unknown warnings. The time window applies to both policies. - -Command-line equivalents: - -```bash -./bin/codex-update-helper config show -./bin/codex-update-helper config set start-time 01:30 end-time 03:00 timezone America/New_York -./bin/codex-update-helper config set restart-policy always -./bin/codex-update-helper config set restart-policy idle-only idle-minutes 15 reopen true -./bin/codex-update-helper config reset -``` - -Multiple values are validated and saved together. An invalid setting leaves the existing file unchanged. Missing settings use the defaults above; a malformed settings file blocks automatic updates until it is fixed or reset. Saved settings are data, never executable shell code. Legacy environment overrides for timezone, start/end hours, and idle seconds take precedence when explicitly supplied. - -## Check it - -```bash -./bin/codex-update-helper status -./bin/codex-update-helper doctor -./bin/codex-update-helper run --dry-run -``` - -The installed command is also available at `~/Applications/Codex Update Helper.app/Contents/Resources/codex-update-helper`. An older `codex-update-helper` on your PATH may still refer to the Homebrew release. - -To install a waiting update immediately, bypassing the time window and keyboard/mouse idle guard: - -```bash -./bin/codex-update-helper run --force -``` - -The configured restart policy, signature checks, bundle identity checks, graceful quitting, and timeouts still apply. `--force` only bypasses the schedule and keyboard/mouse idle guard; it does not change `idle-only` to `always` and never force-kills Codex. - -## Exactly what it does - -- Runs as your macOS user through a LaunchAgent; it never needs `sudo`. -- Enables Codex's automatic update checks and automatic downloads. -- Reads Codex's installed build from `/Applications/ChatGPT.app`. -- Reads updates already staged in Codex's Sparkle cache. -- Verifies the installed and staged apps have bundle ID `com.openai.codex`, OpenAI team ID `2DC432GLL2`, and valid Apple code signatures. -- Uses Codex's native quit confirmation to protect active local tasks and worktrees being created under the default `idle-only` policy. -- Lets Sparkle perform the installation. The helper never downloads or copies Codex. -- Reopens Codex when it was open before the update and the `reopen` setting is enabled. - -It leaves Sparkle's **Skip this version** preference unchanged. - -## Uninstall - -```bash -launchctl bootout "gui/$(id -u)/dev.exprmntl.codex-update-helper" -rm "$HOME/Library/LaunchAgents/dev.exprmntl.codex-update-helper.plist" -``` - -Then remove `~/Applications/Codex Update Helper.app` in Finder. This does not remove Codex, its preferences, or an older Homebrew package. Installer backups are in `~/Library/Application Support/Codex Update Helper/backups/`. - -## Logs - -The local service writes output to: - -```text -~/Library/Logs/Codex Update Helper/service.log -~/Library/Logs/Codex Update Helper/service.error.log -``` - -## Requirements and scope - -- macOS -- The Codex desktop app installed at `/Applications/ChatGPT.app` -- Xcode Command Line Tools to build the helper (no build tools needed at runtime) -- One-time Accessibility permission for the dedicated helper app - -The implementation depends on Codex's current Sparkle staging layout. If that implementation changes, `doctor` should report the mismatch rather than attempting an unsafe installation. - -## Development - -```bash -zsh -n bin/codex-update-helper -./tests/test.sh -# Optional: briefly displays test dialogs in a disposable fixture app. -zsh tests/native-ui.sh -``` - -See [SECURITY.md](SECURITY.md) for the trust model and vulnerability reporting. - -The flat, two-color app icon is maintained as editable vector artwork in `assets/AppIcon.svg`. `scripts/build-icon.sh` uses macOS AppKit to render it and packages all icon sizes with `sips` and `iconutil`. `assets/AppIcon.png` is a portable preview. +| Update window | 2–3 a.m. | Choose start and end times, including overnight windows. | +| Timezone | America/New_York | Choose a timezone; daylight saving time is handled automatically. | +| Restart policy | Only when idle | Allow restarts during active work instead; this can interrupt tasks. Both policies quit gracefully. | +| Inactivity required | 15 minutes | Keyboard/mouse idle time for the default policy; 0 disables this extra check. | +| Retry interval | 15 minutes | How often to retry within the update window. | +| Reopen Codex | On | Reopen after updating if Codex was already open. | -## License +[Manual setup, troubleshooting & technical reference](docs/reference.md) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) · [MIT license](LICENSE) -MIT +Unofficial community utility; not affiliated with or endorsed by OpenAI. diff --git a/docs/reference.md b/docs/reference.md new file mode 100644 index 0000000..d03491d --- /dev/null +++ b/docs/reference.md @@ -0,0 +1,142 @@ +# Setup and technical reference + +[← Project overview](../README.md) + +Detailed instructions for manual setup, agent-assisted installation, troubleshooting, and development. Run commands from the repository root unless a full path is shown. + +## Install + +From the repository on macOS (Xcode Command Line Tools are required to build): + +```bash +zsh scripts/install-local.sh +open "$HOME/Applications/Codex Update Helper.app" +``` + +Enable **Codex Update Helper** once in **System Settings → Privacy & Security → Accessibility**. If it is not listed, use **+** and select the app in your home folder's Applications directory. The helper defers before requesting a quit until this permission is available. Rebuilding an ad-hoc signed helper may require re-enabling its permission. + +### Verify background Accessibility permission + +The settings window and a command launched from Codex can inherit Codex's own Accessibility access. Verify the installed helper from a standalone LaunchAgent before declaring unattended restarts ready; the foreground `doctor` result alone is insufficient. + +Create a temporary, one-shot LaunchAgent with a unique label, `RunAtLoad` enabled, and these `ProgramArguments` (expand `~` to the actual home directory): + +1. `~/Applications/Codex Update Helper.app/Contents/MacOS/codex-update-helper-quit` +2. `--check-accessibility` + +Give it separate stdout/stderr files, load it with `launchctl bootstrap "gui/$(id -u)" /path/to/probe.plist`, and inspect its output and exit status. `ready` with exit 0 means access works; `needs-accessibility` with exit 2 means the permission still needs attention. This check never quits Codex. Unload the temporary job and remove its temporary files afterward. + +If the toggle looks enabled but this check fails, remove the stale **Codex Update Helper** entry from Accessibility, add the currently installed app again using **+**, and enable it. Authenticate when macOS asks. Recheck from the background process. Avoid rebuilding after granting access: the changed ad-hoc signature can invalidate the grant again. + +### Existing installations and scheduling + +The local installer backs up and replaces the existing `dev.exprmntl.codex-update-helper` LaunchAgent, including an older Homebrew installation. It installs a self-contained app under `~/Applications`; no checkout is needed at runtime. Existing Homebrew files are preserved. Do not run `brew services restart codex-update-helper` afterward: that restores the older Homebrew service configuration. Use the local installer to reinstall this version. + +By default, the service attempts updates every 15 minutes between **02:00 inclusive and 03:00 exclusive in `America/New_York`**, following daylight saving time independently of the Mac's timezone. It also requires 15 minutes of keyboard/mouse inactivity. A busy Mac is retried during that hour, then the following night. If the Mac sleeps through the window, the helper skips the daytime wake-up; it does not wake the Mac. The spring-forward date has no 2 a.m. hour, so that night's default update window is skipped. + +Codex's own quit dialog distinguishes active local tasks and worktrees still starting from merely having scheduled tasks enabled. By default, the helper accepts only the exact English scheduled-tasks-only warning. It cancels a recognized quit dialog with any other warning, including active work, and never clicks an unrelated dialog. Unknown/localized dialog structures are left alone and time out without a forced quit. + +## Settings + +Open **Codex Update Helper** from your home folder's Applications directory, or run `./bin/codex-update-helper settings`. The settings window lets you change the schedule and restart behavior. Settings are stored in `~/Library/Application Support/Codex Update Helper/settings.plist` and survive reinstalls. The service reads them each minute; changes take effect on the next check without reinstalling or restarting the service. + +Use the native time pickers for start/end times, the searchable timezone dropdown, and the idle/retry menus. The idle menu disables automatically when you choose to restart during active work. **Restore defaults** fills in the default choices; **Save** applies them. **Cancel** leaves saved settings unchanged. + +| Setting | Default | Behavior | +| --- | --- | --- | +| `start-time` | `02:00` | Start of the update window, in 24-hour HH:MM format. | +| `end-time` | `03:00` | End of the window, exclusive. Windows may cross midnight; start and end must differ. | +| `timezone` | `America/New_York` | Named timezone, including daylight saving changes. | +| `idle-minutes` | `15` | Keyboard/mouse inactivity required for `idle-only`; `0` disables this extra check. | +| `retry-minutes` | `15` | Time between update attempts within the window. | +| `restart-policy` | `idle-only` | Wait for no active local tasks or worktrees being created. `always` permits interrupting active work and ignores keyboard/mouse inactivity. | +| `reopen` | `true` | Reopen Codex if it was open before the update; `false` leaves it closed. | + +The **always** policy still uses a graceful quit and Sparkle's installer. It approves known warnings about active local tasks and worktrees being created, which can interrupt or lose that work. It does not force-kill a hung app, bypass signature checks, or approve unknown warnings. The time window applies to both policies. + +Command-line equivalents: + +```bash +./bin/codex-update-helper config show +./bin/codex-update-helper config set start-time 01:30 end-time 03:00 timezone America/New_York +./bin/codex-update-helper config set restart-policy always +./bin/codex-update-helper config set restart-policy idle-only idle-minutes 15 reopen true +./bin/codex-update-helper config reset +``` + +Multiple values are validated and saved together. An invalid setting leaves the existing file unchanged. Missing settings use the defaults above; a malformed settings file blocks automatic updates until it is fixed or reset. Saved settings are data, never executable shell code. Legacy environment overrides for timezone, start/end hours, and idle seconds take precedence when explicitly supplied. + +## Check it + +```bash +./bin/codex-update-helper status +./bin/codex-update-helper doctor +./bin/codex-update-helper run --dry-run +``` + +The installed command is also available at `~/Applications/Codex Update Helper.app/Contents/Resources/codex-update-helper`. An older `codex-update-helper` on your PATH may still refer to the Homebrew release. + +To install a waiting update immediately, bypassing the time window and keyboard/mouse idle guard: + +```bash +./bin/codex-update-helper run --force +``` + +The configured restart policy, signature checks, bundle identity checks, graceful quitting, and timeouts still apply. `--force` only bypasses the schedule and keyboard/mouse idle guard; it does not change `idle-only` to `always` and never force-kills Codex. + +## Exactly what it does + +- Runs as your macOS user through a LaunchAgent; it never needs `sudo`. +- Enables Codex's automatic update checks and automatic downloads. +- Reads Codex's installed build from `/Applications/ChatGPT.app`. +- Reads updates already staged in Codex's Sparkle cache. +- Verifies the installed and staged apps have bundle ID `com.openai.codex`, OpenAI team ID `2DC432GLL2`, and valid Apple code signatures. +- Uses Codex's native quit confirmation to protect active local tasks and worktrees being created under the default `idle-only` policy. +- Lets Sparkle perform the installation. The helper never downloads or copies Codex. +- Reopens Codex when it was open before the update and the `reopen` setting is enabled. + +It leaves Sparkle's **Skip this version** preference unchanged. + +## Uninstall + +```bash +launchctl bootout "gui/$(id -u)/dev.exprmntl.codex-update-helper" +rm "$HOME/Library/LaunchAgents/dev.exprmntl.codex-update-helper.plist" +``` + +Then remove `~/Applications/Codex Update Helper.app` in Finder. This does not remove Codex, its preferences, or an older Homebrew package. Installer backups are in `~/Library/Application Support/Codex Update Helper/backups/`. + +## Logs + +The local service writes output to: + +```text +~/Library/Logs/Codex Update Helper/service.log +~/Library/Logs/Codex Update Helper/service.error.log +``` + +## Requirements and scope + +- macOS +- The Codex desktop app installed at `/Applications/ChatGPT.app` +- Xcode Command Line Tools to build the helper (no build tools needed at runtime) +- One-time Accessibility permission for the dedicated helper app + +The implementation depends on Codex's current Sparkle staging layout. If that implementation changes, `doctor` should report the mismatch rather than attempting an unsafe installation. + +## Development + +```bash +zsh -n bin/codex-update-helper +./tests/test.sh +# Optional: briefly displays test dialogs in a disposable fixture app. +zsh tests/native-ui.sh +``` + +See [SECURITY.md](../SECURITY.md) for the trust model and vulnerability reporting. + +The flat, two-color app icon is maintained as editable vector artwork in `assets/AppIcon.svg`. `scripts/build-icon.sh` uses macOS AppKit to render it and packages all icon sizes with `sips` and `iconutil`. `assets/AppIcon.png` is a portable preview. + +## License + +MIT