Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ All notable changes are documented here. The project follows semantic versioning

### Added

- Explicit `--takeover-at-login` installation mode for automatic theme recovery when macOS restores Codex during boot.
- A one-shot 120-second startup handoff that revalidates one official PID, uses normal app quit, confirms complete exit, and fails closed without signals or force quit.
- LaunchServices-based managed startup with real official PID discovery and transient app-discovery retry behavior.
- Self-contained per-user runtime installation with an atomic versioned `current` release.
- User LaunchAgent commands: `install-agent`, `upgrade-agent`, `switch`, `pause`, `resume`, and `uninstall-agent`.
- Portable `release:check` command and CI gate for tests, themes, types, build, production dependency audit, public-file hygiene, and diff whitespace.
Expand Down
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Every theme below is a complete local package under `themes/`. The left image is
| <img src="themes/satoru-gojo/background.jpg" alt="Satoru Gojo theme background" width="640"> | <img src="docs/gallery/satoru-gojo/marketing.jpg" alt="Satoru Gojo marketing preview" width="640"> |

```bash
./bin/awesome-codex-themes install-agent satoru-gojo
./bin/awesome-codex-themes install-agent satoru-gojo --takeover-at-login
```

### 02. Zaun Workshop
Expand Down Expand Up @@ -186,11 +186,13 @@ cd Awesome-codex-themes
Install the Featured theme as the persistent selection:

```bash
./bin/awesome-codex-themes install-agent satoru-gojo
./bin/awesome-codex-themes install-agent satoru-gojo --takeover-at-login
./bin/awesome-codex-themes status
```

If Codex is already open without this project's managed CDP endpoint, the agent reports `restart-required` and does not close it. Save your work, quit Codex yourself, and let the installed agent start the verified official app. See [Installation and recovery](docs/INSTALL.md) before enabling persistence.
`--takeover-at-login` is the explicit opt-in that keeps the theme present after a Mac reboot even when macOS restores an ordinary Codex process first. During the first 120 seconds after boot, the agent may request one normal quit of the single verified official process, confirm that exact process is gone, then reopen it through LaunchServices with the saved profile and managed local endpoint. Outside that window, without the flag, with multiple instances, or if identity/exit verification fails, the agent leaves Codex running and reports `restart-required`.

If Codex is already open during normal work, save your work and quit it yourself before the first managed launch. See [Installation and recovery](docs/INSTALL.md) before enabling persistence.

**Best-effort injection is attempted on every numeric Codex Desktop version. Highly compatible and live-verified: `26.707.*` and `26.715.*`.** Other versions are attempted, but their component layout is not guaranteed.

Expand Down Expand Up @@ -222,7 +224,7 @@ After an official Codex update, the agent attempts the shared adapter again. If

## Current status

Version `0.4.2` includes the engine, twelve complete local theme packages, self-contained user installation, LaunchAgent persistence, conflict diagnostics, safe restore, and a static Gallery.
Version `0.4.3` includes the engine, twelve complete local theme packages, self-contained user installation, opt-in bounded login takeover, LaunchAgent persistence, conflict diagnostics, safe restore, and a static Gallery.

| Capability | State |
| --- | --- |
Expand All @@ -232,7 +234,7 @@ Version `0.4.2` includes the engine, twelve complete local theme packages, self-
| Loopback-only apply, idempotent reapply, and owned-state removal | Implemented and prototype verified |
| Install, upgrade, switch, pause, resume, status, and uninstall | Integration verified on `26.715.21425` |
| Renderer reload and full app relaunch recovery | Integration verified on `26.715.21425` |
| Physical macOS reboot | Pending direct exercise |
| Opt-in macOS login takeover | Implemented and automated; physical reboot still pending direct exercise |
| Searchable static Gallery | Implemented; deployment is separate from the repository build |

## Commands
Expand All @@ -242,7 +244,7 @@ Version `0.4.2` includes the engine, twelve complete local theme packages, self-
| `list` | Validate and list complete runnable themes. |
| `doctor` | Inspect the signed app, exact running PIDs, and known injector conflicts without mutation. |
| `start <theme>` | Start one session-scoped managed Codex launch. |
| `install-agent <theme>` | Install the versioned runtime and enable persistent management. |
| `install-agent <theme> [--takeover-at-login]` | Install persistence; the optional flag explicitly permits one bounded login-time handoff after reboot. |
| `upgrade-agent` | Upgrade the installed runtime while preserving theme and enabled/paused state. |
| `switch <theme>` | Validate and select another installed theme. |
| `pause` | Disable persistent management and remove project-owned live styling. |
Expand All @@ -260,7 +262,7 @@ Version `0.4.2` includes the engine, twelve complete local theme packages, self-
- Selects only the expected main `app://-/index.html` renderer.
- Applies one namespaced style element and one optional inert, pointer-transparent decorative node.
- Never reads conversations, account tokens, API keys, model settings, or unrelated user data.
- Never patches `app.asar`, modifies the signed app bundle, uses `--user-data-dir`, or silently terminates an active Codex process.
- Never patches `app.asar`, modifies the signed app bundle, or uses `--user-data-dir`. Process handoff is disabled by default and is allowed only after explicit `--takeover-at-login` consent, for one verified official PID inside the bounded startup window.
- `pause`, `restore`, and `uninstall-agent` remove only project-owned runtime state.

Read [SECURITY.md](SECURITY.md), [docs/SAFETY.md](docs/SAFETY.md), and [docs/MIGRATION.md](docs/MIGRATION.md) before replacing another injector.
Expand Down
4 changes: 2 additions & 2 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ The public CLI keeps `_watch` and `_agent` internal. The shell entrypoint finds
```text
Git clone (mutable source)
→ validated staging copy
→ ~/Library/Application Support/AwesomeCodexThemes/releases/0.4.2/
→ ~/Library/Application Support/AwesomeCodexThemes/releases/0.4.3/
→ atomic current symlink
→ ~/Library/LaunchAgents/io.github.awesome-codex-themes.agent.plist
→ current/bin/awesome-codex-themes _agent
```

The service never points at the clone. Configuration and state remain outside immutable release directories, use owner-only permissions, and are written atomically. Reinstallation boots out only this project's label, updates the installed plist/current release, bootstraps, and kickstarts it. Uninstall removes only project-owned paths.

An enabled agent owns the CDP-enabled launch lifecycle. If an ordinary Dock launch is already running, it reports `restart-required` rather than terminating or relaunching it. This is the unavoidable open-source CDP boundary: the project can persistently inject only into an official process that was started with its verified loopback debugging endpoint.
An enabled agent owns the CDP-enabled launch lifecycle. If an ordinary Dock launch is already running, it normally reports `restart-required` rather than touching it. Users who explicitly install with `--takeover-at-login` permit one narrowly bounded exception: during the first 120 seconds after boot, a single revalidated official PID may receive a normal macOS quit request, and only a confirmed complete exit is followed by a LaunchServices reopen. Multiple processes, changed identity, timeout, or any later session fail closed without force termination. This handles the macOS restore race while preserving the open-source CDP boundary.

## Theme catalog and static gallery

Expand Down
14 changes: 11 additions & 3 deletions docs/INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,23 @@ It does not edit `ChatGPT.app`, `Codex.app`, Codex conversations, settings, cred
## Install Satoru Gojo

```bash
./bin/awesome-codex-themes install-agent satoru-gojo
./bin/awesome-codex-themes install-agent satoru-gojo --takeover-at-login
./bin/awesome-codex-themes status
```

The installed configuration selects `satoru-gojo`, enables persistence, and starts the user LaunchAgent. The agent uses a dynamic literal-loopback CDP port and does not pass `--user-data-dir`.

The optional `--takeover-at-login` flag is explicit consent for a single bounded handoff when macOS restores Codex before the agent can open its managed endpoint. It is the mode to use when the theme should return automatically after reboot. Without the flag, unmanaged Codex processes are always left untouched.

## Reboot and login handoff

The handoff is permitted only inside a 120-second startup window and only when exactly one official Codex process is present. The agent revalidates the signed application and exact PID, sends the normal macOS quit request, waits until that PID is gone with no replacement process, then opens the same official app through LaunchServices with a dynamic `127.0.0.1` endpoint. It does not use another `--user-data-dir`, so the existing Codex profile remains in place.

If the startup window has expired, more than one official process exists, the PID changes, or normal quit cannot be confirmed, the agent fails closed to `restart-required`. It does not escalate to `kill`, `kill -9`, or broad process matching.

## First transition

If Codex is already running without a trusted endpoint, status becomes `restart-required`. This is deliberate: the agent never terminates an active session.
If Codex is already running without a trusted endpoint outside the explicitly approved startup handoff, status becomes `restart-required`. This protects an active work session.

1. Save any active work.
2. Quit the official Codex app yourself.
Expand Down Expand Up @@ -110,6 +118,6 @@ If `launchctl bootout` reports that the service is not loaded, continue with the
| `idle` | Agent is installed but has not completed a managed launch. | Wait briefly, then run `status`. |
| `starting` | A verified managed app launch is in progress. | Wait; do not start another app copy. |
| `active` | The selected theme is verified on the managed renderer. | None. |
| `restart-required` | Codex is running without the managed endpoint. | Save work and quit it yourself. |
| `restart-required` | Codex is running without the managed endpoint, or a safe login handoff was not allowed/confirmed. | Save work and quit it yourself. |
| `paused` | Persistence is disabled and owned live styling has been removed when reachable. | Run `resume` when desired. |
| `error` | A stable error code was recorded. | Run `doctor`, inspect logs, and use manual recovery if necessary. |
2 changes: 1 addition & 1 deletion docs/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The read-only report recognizes known legacy LaunchAgents, legacy scripts, and C
3. Confirm its LaunchAgent is unloaded and its owned renderer style is absent.
4. Quit Codex yourself if it is still running with the old endpoint.
5. Run `doctor` again.
6. Install this project with `install-agent satoru-gojo`.
6. Install this project with `install-agent satoru-gojo --takeover-at-login` when reboot persistence is desired.
7. Check `status` and complete the first transition described in [INSTALL.md](INSTALL.md).

Do not delete an unfamiliar plist or send signals to an unverified PID. A legacy injector can contain unrelated user configuration, and this project deliberately does not claim ownership of it.
Expand Down
10 changes: 5 additions & 5 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ The portable gate runs the full test/theme/type/build suite, the production depe
Use an explicitly approved test session on a live-verified official Codex version. Never terminate an active user session to satisfy this checklist.

1. Record `doctor` output and resolve any legacy injector conflict through that injector's documented restore path.
2. Install with `install-agent satoru-gojo` while Codex is already open and confirm `restart-required` without automatic termination.
2. Install without the takeover flag while Codex is already open and confirm `restart-required` without automatic termination.
3. Quit Codex explicitly and confirm the agent starts the verified official app on a dynamic literal-loopback port.
4. Confirm `active`, the existing Codex profile, and the Satoru Gojo presentation.
5. Reload the renderer and confirm idempotent reapply without duplicate owned nodes or styles.
6. Exercise keyboard focus, menus, Composer, code/diff surfaces, reduced motion, and owned-state restore.
7. Run `pause`, confirm owned styling is removed, and confirm Codex can remain closed.
8. Run `resume`, close the managed app, and confirm the agent starts a new managed process with the saved theme.
9. Log out/in or reboot the approved test Mac and confirm LaunchAgent startup.
9. Reinstall with `install-agent satoru-gojo --takeover-at-login`, reboot the approved test Mac, and confirm the bounded handoff or direct managed startup restores the theme.
10. Confirm an unverified numeric-version fixture attempts `codex-best-effort`; if verification fails, confirm `pause` or `restore` returns the official UI.
11. Run `uninstall-agent`, then verify the plist, installed support directory, owned renderer state, and service are gone while the official Codex profile remains intact.
12. Exercise the manual `launchctl bootout` recovery from [INSTALL.md](INSTALL.md).
Expand All @@ -52,15 +52,15 @@ Before approval is executed, verify:
- the repository description, topics, default branch, and security-advisory link are correct;
- the owner understands that forks, caches, and downloaded release assets cannot be recalled reliably after publication.

## 5. Main and `v0.4.2`
## 5. Main and `v0.4.3`

After the source, lifecycle, and visibility gates pass:

1. Land the reviewed release commit on `main` without overwriting unrelated local work.
2. Rerun `pnpm check` from the exact `main` commit.
3. Push `main` and confirm GitHub Actions succeeds on that SHA.
4. Create the annotated `v0.4.2` tag from the verified commit.
4. Create the annotated `v0.4.3` tag from the verified commit.
5. Publish a GitHub Release that links to [INSTALL.md](INSTALL.md), [MIGRATION.md](MIGRATION.md), [SAFETY.md](SAFETY.md), and the exact live-verified Codex ranges while explaining the best-effort fallback.
6. Confirm a fresh public clone can run `doctor`, `list`, an isolated `install-agent satoru-gojo` flow, and an `upgrade-agent` flow that preserves a paused configuration.
6. Confirm a fresh public clone can run `doctor`, `list`, an isolated `install-agent satoru-gojo --takeover-at-login` flow, and an `upgrade-agent` flow that preserves paused and takeover configuration.

Do not describe login/reboot persistence as publicly verified until both the local lifecycle record and the CI/release SHA are available.
13 changes: 8 additions & 5 deletions docs/SAFETY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ It does not trust:
1. Discover the official `ChatGPT.app` or legacy `Codex.app` bundle.
2. Verify code signature integrity, bundle ID `com.openai.codex`, Team ID `2DC432GLL2`, architecture, and bundled Node version.
3. Refuse a managed launch if an exact official app process is already running without this project's trusted endpoint.
4. Select an unused non-privileged port and launch the inspected executable with `--remote-debugging-address=127.0.0.1`.
4. Select an unused non-privileged port and launch the inspected app through macOS LaunchServices with `--remote-debugging-address=127.0.0.1`.
5. Verify the listener address and confirm its PID belongs to the inspected official app.
6. Query `/json/list` only on literal loopback and accept only the expected main `app://-/index.html` renderer.
7. Load a local theme and validate its manifest, paths, sizes, CSS, and live-verified Codex version metadata.
Expand All @@ -38,9 +38,11 @@ It does not trust:
3. Generate a user LaunchAgent that calls only the stable installed launcher.
4. Boot out only this project's existing label, then bootstrap and kickstart the replacement.
5. If Codex is absent, launch the verified official executable with a dynamic `127.0.0.1` CDP port and no alternate data directory.
6. If Codex is already running unmanaged, record `restart-required` and leave it untouched.
7. Reapply idempotently while the verified managed process and endpoint remain valid.
8. After a Codex version change, attempt the verified or best-effort adapter and report a normal typed error if renderer verification fails.
6. If Codex is already running unmanaged, record `restart-required` and leave it untouched by default.
7. Only after explicit `--takeover-at-login` consent, within 120 seconds of boot, and with exactly one revalidated official PID, request one normal macOS quit and confirm complete exit before a managed relaunch.
8. Never escalate a login handoff to a signal, force quit, wildcard process match, or second attempt; any ambiguity fails closed to `restart-required`.
9. Reapply idempotently while the verified managed process and endpoint remain valid.
10. After a Codex version change, attempt the verified or best-effort adapter and report a normal typed error if renderer verification fails.

## Restore sequence

Expand All @@ -65,8 +67,9 @@ For an installed persistent agent, `pause` and no-port `restore` first set `enab
- An enabled persistent agent may relaunch Codex after it exits; use `pause` before intentionally keeping the app closed.
- An official app update may receive a best-effort theme immediately; no claim of visual compatibility is made until that version is recorded as verified.
- Malformed state is reported and not silently discarded.
- Temporary app-discovery failures during login are recorded and retried by the persistent loop instead of disabling the service.
- Concurrent third-party theme injectors are unsupported because their high-specificity rules can override either theme. Restore or disable the other theme before evaluating Awesome Codex Themes; this engine never deletes unrelated style elements.

## Non-goals

The engine does not provide a security boundary against a malicious local administrator or a compromised official application. It does not secure CDP for unrelated software, sign a desktop distribution, intercept an ordinary Dock launch, or guarantee visual compatibility on unverified Codex versions.
The engine does not provide a security boundary against a malicious local administrator or a compromised official application. It does not secure CDP for unrelated software, sign a desktop distribution, permanently intercept every ordinary Dock launch, or guarantee visual compatibility on unverified Codex versions.
Loading
Loading