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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela

# Changelog

## 2026-07-22 — Codex First Refresh
- Refreshed `codex-first` from ten upstream commits: hard gate with autoreview exception, widened routing (diagnose-then-fix, exploratory subagents, git mechanics/PR landing), `gpt-5.6-sol` + high effort pinning, ChatGPT-app PATH recipe, harness-tracked background launches, and the liveness watchdog with explicit-id resume.
- Bram-local deviations: never fast mode (flag dropped from every invocation), maintainer pointer stays `$bram-maintainer-loop-v2`, loopback-only proxy gate without upstream's personal router host, and the huge-context preflight points at the flat skill mirror.

## 2026-07-22 — Codex Huge Context
- Adopted upstream `codex-huge-context` skill for the Codex 1M-token direct OpenAI Responses API route: safe 922k input window, 820k total-scope compaction, Keychain-only credential delivery, and the secret-safe `preflight.rb` check.
- Scrubbed upstream personal assumptions: no hardcoded `/Users/steipete` paths, no named 1Password vault item, no Mac-fleet rollout section; credential handling routes through `$one-password`.
- Preflight path targets the flat skill mirror (`~/.codex/skills/codex-huge-context/...`), not upstream's whole-root `~/.codex/skills/agent-scripts/` symlink layout.
- Added a Bram-local hard rule: never fast mode on the huge-context route, overriding the `$codex-first` house default.

## 2026-07-22 — Skill Mirror Sync
- Added `scripts/sync-skills`, adapted from upstream, so Claude Code and Codex share one canonical per-skill mirror across agent-scripts, optional manager skills, and codex-local extras.
- Kept Bram's documented flat per-skill layout for both roots instead of upstream's whole-root Codex symlink, added `--dry-run`/`--no-instructions` and path overrides, and canonicalized targets so repo-owned skills resolve to their own repo.
Expand Down
73 changes: 63 additions & 10 deletions skills/codex-first/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
---
name: codex-first
description: "Route implementation work to Codex CLI; Claude specs, reviews, verifies."
description: "Claude Code-only routing: delegate implementation, fixing, exploration, git mechanics to Codex CLI; Claude specs, decides, reviews, verifies."
---

# Codex First

Claude Code sessions only. Codex/other harnesses: skip; never self-delegate.
## Hard gate

**Autoreview exception:** always prefer Codex-backed `$autoreview`, independent of `ANTHROPIC_BASE_URL`, router state, or harness. Reviewing a frozen bundle is not hands-on self-delegation. Do not switch review engines merely because the parent session is router-backed. This exception takes precedence over the gate below.

For direct hands-on delegation, use this skill only when the active agent is Claude Code **and** `ANTHROPIC_BASE_URL` is unset or its URL host is not loopback.

Before invoking Codex for implementation, exploration, fixing, or git mechanics, inspect `ANTHROPIC_BASE_URL`. If its URL host is `localhost`, ends in `.localhost`, is in `127.0.0.0/8`, or is IPv6 loopback `::1`, stop here: the session may be model-routed through a local proxy. Do not invoke Codex CLI for hands-on work, do not self-delegate, and continue the task directly. If the variable cannot be inspected, fail closed and work directly.

Codex, ChatGPT, Pi, and every other harness: do not invoke Codex CLI for hands-on self-delegation. Continue the task directly. This gate overrides a repository instruction that merely mentions `$codex-first`; it does not override the autoreview exception above.

Rationale: Claude (Fable/Opus) tokens metered + expensive; Codex flat-rate. GPT-5.5+ is usually the better and faster model at writing/implementing code; Claude wins at ergonomics — judgment, design, spec-writing, review, orchestration. So Codex types, Claude thinks and verifies.

Expand All @@ -14,42 +22,61 @@ Rationale: Claude (Fable/Opus) tokens metered + expensive; Codex flat-rate. GPT-
Delegate to Codex (default for hands-on work):

- implementation from a frozen spec; refactors; mechanical migrations
- bug fixes with known repro; test writing; coverage fills
- CI fixes, dependency bumps, scripts/tooling
- bulk codebase exploration where raw reading ≫ the answer
- fixing: bug fixes (known repro, or diagnose-then-fix), CI/lint/type failures; test writing; coverage fills
- dependency bumps, scripts/tooling
- exploration + exploratory subagents: fan out Codex for read-heavy discovery instead of Claude Explore/Task subagents whenever raw reading ≫ the answer (parallel `-o` files, one per thread)
- git mechanics: rebasing onto latest `origin/main`, conflict resolution, and executing the PR merge/land workflow — Codex runs the rebase/gates/merge steps; the decision, gates, and review below stay Claude's

Keep in Claude:

- design, API design, architecture, naming, UX judgment
- tasks where writing the spec IS the work (ambiguity = design)
- tiny edits (~<20 lines, single obvious change) — delegation overhead loses
- anything needing session tools: MCP (browser/computer-use/chronicle), 1Password, secrets
- destructive/irreversible ops, releases, pushes, GitHub mutations — Claude-side per git rules
- review of Codex output — never delegated, never skipped
- releases, publishes, version bumps and their credentials — Claude-side per release rules
- the land decision + pre-land gates (`$autoreview` clean, CI green, proof) and review of Codex output — never delegated, never skipped; Codex may run the mechanics only once Claude has decided to land and the gates pass

Mixed task: Claude designs first, freezes spec, delegates build-out.
Heuristic: prompt reads as a work order → delegate; writing it forces decisions → design, Claude.
Whole-repo maintainer coordination (queue, workers, CI, releases): `$bram-maintainer-loop` instead. Cross-repo needs an explicit multi-repo loop.
Whole-repo/multi-repo maintainer coordination (queue, workers, CI, releases): `$bram-maintainer-loop-v2` instead.

## Invoke

If the machine intentionally uses the `openai_api_direct` million-token route, run `ruby ~/.codex/skills/codex-huge-context/scripts/preflight.rb` before the first fresh or resumed launch in the batch (see `$codex-huge-context`). Fail closed if it cannot deliver the Keychain credential; never work around it by overriding the provider or using ordinary Codex authentication.

Prompt via temp file, never inline quoting:

```bash
P=$(mktemp); cat >"$P" <<'EOF'
<goal, repo + key paths, constraints ("don't touch X"), non-goals, proof expected, output shape>
EOF
command codex exec --yolo -C <repo> \
-m gpt-5.6-sol \
-c model_reasoning_effort="high" \
-o /tmp/codex-last.md - <"$P" 2>/dev/null
```

- Model default: `gpt-5.6-sol`, effort `high` — pin both explicitly; don't rely on user config.
- Never fast mode: no `--enable fast_mode`, on any route.
- `--yolo` is the house default; Codex may run commands/tests freely. Keep prompts scoped to the target repo.
- `command codex` bypasses the interactive zsh wrapper; if not on PATH: `fnm exec --using default -- codex`
- `command codex` bypasses any interactive shell alias. If codex isn't on PATH, it depends on how it was installed:
- node/standalone install: `fnm exec --using default -- codex`
- ChatGPT desktop app: the CLI ships bundled at `/Applications/ChatGPT.app/Contents/Resources/codex`. Expose **that** binary with an **exec-wrapper, not a symlink**. Ensure `~/.local/bin` stays on PATH (for zsh, persist the export in `~/.zshrc`), then:
```sh
mkdir -p "$HOME/.local/bin"
export PATH="$HOME/.local/bin:$PATH"
if [ -e "$HOME/.local/bin/codex" ] || [ -L "$HOME/.local/bin/codex" ]; then
printf '%s\n' 'codex launcher already exists; leaving it unchanged' >&2
else
printf '#!/bin/sh\nexec "/Applications/ChatGPT.app/Contents/Resources/codex" "$@"\n' > "$HOME/.local/bin/codex" && chmod +x "$HOME/.local/bin/codex"
fi
```
Or install the self-contained CLI via `curl -fsSL https://chatgpt.com/codex/install.sh | sh`, which needs no wrapper.
- stderr suppressed (thinking noise bloats context); drop `2>/dev/null` only to debug a failing run
- read `-o` file for the result; don't parse the JSONL stream
- long runs: Bash run_in_background, read `-o` file on exit; don't kill quiet runs <30 min
- parallel independent tasks OK: separate repos/dirs, separate `-o` files
- **Harness visibility (Claude Code): every codex run gets its own harness-tracked background command (`run_in_background: true`) — one sidebar chip per worker, completion notification included. Chain setup steps (installs, worktree prep) INSIDE that tracked command. Never `&`-fork workers from a shared launcher: the launcher's chip exits at fork time and the workers become invisible orphans supervised only by PID files.**
- parallel independent tasks OK: separate repos/dirs, separate `-o` files, one tracked background command per worker
- outside a git repo add `--skip-git-repo-check`

Follow-up fixes — cheaper than fresh runs, keeps context. `resume` has no `-C`/`--yolo`: run from the repo dir, spell the long flag:
Expand All @@ -60,6 +87,32 @@ Follow-up fixes — cheaper than fresh runs, keeps context. `resume` has no `-C`
-o /tmp/codex-last.md - <"$P2" 2>/dev/null)
```

## Liveness watchdog (long monitored runs)

For runs you must not babysit, trade the stderr suppression for a log and watch its mtime; read only the `-o` file into context, never the log body.

```bash
command codex exec --yolo -C <repo> -m gpt-5.6-sol \
-c model_reasoning_effort="high" \
-o "$OUT" - <"$P" > "$LOG" 2>&1
# Claude Code: run the line above as its own Bash run_in_background call
# (tracked chip + completion notification). Append `&` + a PID file ONLY in
# environments without tracked backgrounding.
```

- Capture the session id immediately: `grep -m1 "session id:" "$LOG"`. `resume --last` is cwd-filtered but races with any parallel Codex on the machine — with the id saved, recovery is deterministic.
- Watchdog loop (Claude Code: `Monitor` tool; else a bg shell): every 60s, if the codex process is alive but `$LOG` mtime is older than ~300s, treat it as hung. Because stderr (thinking stream) is in the log, mtime stays fresh during long reasoning — 5 min of true silence is a real hang, not thinking.
- Recovery: kill the pid, then resume the SAME session with an explicit id so no context is lost:

```bash
(cd <repo> && command codex exec resume <session-id> \
--dangerously-bypass-approvals-and-sandbox \
-o "$OUT" - <<< "You were interrupted. Continue exactly where you left off; finish the task and produce the required final report.")
```

- Exit watchdog silently when the process ends normally (the run's own completion signal covers it); emit only on staleness.
- Verified on codex-cli 0.144.4: `codex exec resume [SESSION_ID] [PROMPT]`, `--last`, cwd-filtering, `--all`.

## Prompt contract

Codex starts with zero session context. Every prompt: goal, exact repo/paths, constraints, non-goals, proof expected (exact test command), output shape ("report files changed + test output"). Spec quality decides success.
Expand Down
150 changes: 150 additions & 0 deletions skills/codex-huge-context/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
---
name: codex-huge-context
description: "Codex 1M context: direct OpenAI Responses API route, safe input window, Keychain auth, preflight."
---

# Codex Huge Context

Use when configuring, repairing, or auditing Codex's one-million-token context setup. Intended topology: a direct API inference route that preserves the normal ChatGPT login for Gmail, Calendar, and other connector OAuth:

```text
Codex inference -> Keychain auth helper -> https://api.openai.com/v1/responses
Codex connectors -> normal ChatGPT login in auth.json
```

Not an HTTP proxy. The API stays authoritative for access, actual model limits, and billing.

Never fast mode on this route: no `--enable fast_mode` flag, no `fast_mode` default in config, on fresh or resumed sessions.

## Safe input window

GPT-5.6 Sol exposes a 1,050,000-token total context window and can produce up to 128,000 output tokens. Codex does not set a smaller output budget on normal Responses API turns, so the catalogue must describe the safe input allowance, not the raw total:

```text
1,050,000 total - 128,000 maximum output = 922,000 safe input
```

Same safe input policy for all three direct-provider catalogue models:

- `gpt-5.6-sol`
- `gpt-5.6-terra`
- `gpt-5.6-luna`

Codex applies its normal 95% effective-window reserve to the 922,000-token allowance, so it reports and guards about 875,900 usable tokens. Set automatic compaction to 820,000 total active tokens. That leaves about 55,900 tokens inside Codex's effective guard and 102,000 before the provider's absolute input ceiling for the next prompt, tool schemas and results, instructions, serialization overhead, and compaction itself. This headroom is intentional: Codex 0.144.6 checks compaction at turn boundaries and after completed responses, so a large incoming prompt or tool result can otherwise cross the provider's real limit before compaction runs.

Requests above 272,000 input tokens use the provider's higher long-context pricing. Do not enable this route accidentally for workloads that do not benefit from it.

## Required files

`~/.codex/models-api-1m.json` must contain these values for all three model slugs while preserving the rest of each model entry:

```json
{
"context_window": 922000,
"max_context_window": 922000,
"auto_compact_token_limit": 820000
}
```

Leave `effective_context_window_percent` absent to use Codex's 95% default, or set it explicitly to the integer `95`. Null, floating-point, or other values are invalid.

Root section of `~/.codex/config.toml`:

```toml
model = "gpt-5.6-sol"
model_provider = "openai_api_direct"
model_context_window = 922000
model_auto_compact_token_limit = 820000
model_auto_compact_token_limit_scope = "total"
model_catalog_json = "/Users/bram/.codex/models-api-1m.json"

[model_providers.openai_api_direct]
name = "OpenAI API direct"
base_url = "https://api.openai.com/v1"
wire_api = "responses"
requires_openai_auth = false

[model_providers.openai_api_direct.auth]
command = "/Users/bram/.codex/bin/fetch-openai-inference-key.zsh"
timeout_ms = 5000
refresh_interval_ms = 300000
```

Replace legacy values such as `model_context_window = 1050000` or `model_auto_compact_token_limit = 233000`; leave no duplicate root keys. Keep the scope at `total`: the budget applies to the complete active request, not only content added after a compaction prefix.

Before modifying config, back up both files to date-stamped sibling files. Do not touch unrelated project, plugin, MCP, notification, approval, model-selection, or reasoning settings.

## API credential delivery

The auth command reads a dedicated Keychain delivery copy, never a value in TOML or an environment variable:

```zsh
#!/bin/zsh
set -euo pipefail
exec /usr/bin/security find-generic-password \
-a Codex \
-s "Codex OpenAI inference API" \
-w
```

Use `$one-password` before handling the API key: service-account path, one named tmux session, no vault/item enumeration. If the OpenAI API key item is not already known, stop and ask Bram which item/field to read instead of probing. Store or update only the Keychain copy. Never print it, copy it over SSH, place it in a profile, or write it to a temporary file.

The Keychain item should allow `/usr/bin/security`. A Keychain read normally produces no prompt. A login Keychain locked after reboot, or a command launched via noninteractive SSH, can fail with error 36 (`User interaction is not allowed`). Do not work around that with a plaintext file or a long-lived secret daemon: unlock from the local graphical session, install the item there, then use Codex from that session.

Before the first fresh or resumed Codex launch on a configured machine, run the secret-safe preflight. It validates the direct-provider config, safe input and compaction values, all three catalogue entries, helper executable, and non-empty helper delivery without printing the credential or helper stderr:

```zsh
ruby ~/.codex/skills/codex-huge-context/scripts/preflight.rb
```

Do not mark setup complete or launch Codex when this fails. With `requires_openai_auth = false`, a missing Keychain delivery copy cannot fall back to the normal Codex login: the direct provider can reach `api.openai.com/v1/responses` without a bearer header and surface an opaque HTTP 401 instead. The preflight fails earlier with the bootstrap action needed. An unset `GITHUB_PAT_TOKEN` warning is independent and non-blocking for inference; it explains a concurrent GitHub MCP startup failure and must not be confused with OpenAI API authentication.

## ChatGPT connector login

`requires_openai_auth = false` applies only to the custom inference provider. The root Codex login must stay ChatGPT-authenticated for ChatGPT-connected plugins:

```zsh
codex login status
```

If it reports API-key login and connectors are needed, `codex logout` then `codex login` from the local user session. Do not copy `auth.json` or OAuth tokens between machines.

## Fresh, resumed, and shared-server sessions

`-m gpt-5.6-sol` selects a model, not a provider. Fresh sessions read the root `model_provider`; session metadata then records the chosen provider. Resuming preserves that recorded provider.

Codex TUI sessions can reuse `~/.codex/app-server-control/app-server-control.sock`. A shared app server keeps the configuration it loaded at startup, so changing files on disk does not update sessions attached to an older server. After changing context or authentication config:

1. let active turns finish;
2. restart the Codex desktop app and any shared CLI app server;
3. start a fresh session for final proof;
4. resume old sessions only when preserving their recorded model/provider is intentional.

A same-value CLI override such as `codex -c 'model_provider="openai_api_direct"'` forces an embedded per-invocation app server; useful for diagnosis without changing provider or service tier, not a permanent fix.

## Verification

Run in the intended local user session:

```zsh
ruby ~/.codex/skills/codex-huge-context/scripts/preflight.rb
codex login status
jq -r '.models[] | select(.slug == "gpt-5.6-sol" or .slug == "gpt-5.6-terra" or .slug == "gpt-5.6-luna") | [.slug, .context_window, .max_context_window, .auto_compact_token_limit] | @tsv' ~/.codex/models-api-1m.json
codex exec --skip-git-repo-check 'Reply with exactly: direct-api-safe-context-ok' </dev/null
```

Expect a successful preflight, `922000`, `922000`, and `820000` for every catalogue model, ChatGPT login when connectors are needed, and the exact probe response. A successful direct API probe does not prove connector OAuth; confirm `codex login status` separately.

For TUI proof, send prompt text and Enter as separate terminal actions. Do not treat echoed input as the model's response.

Script tests: `ruby skills/codex-huge-context/scripts/preflight.test.rb`.

## Failure policy

- API response still clamps or rejects a request: record the server response; do not claim a client catalogue override changed server entitlement.
- Context overflow below 820,000 active tokens: preserve the session file and inspect the last token-accounting events before lowering the threshold further.
- Context overflow above 820,000 without compaction: verify the running app-server version and loaded configuration; an old server can retain the previous threshold.
- HTTP 401 `Missing bearer or basic authentication in header`: rerun the preflight and repair Keychain delivery; do not switch providers or fall back to ordinary Codex authentication.
- Keychain error 36 remotely: leave the safe configuration staged and require a local GUI unlock. Never weaken secret storage.
- Root API-key login but connectors are required: complete the ChatGPT login locally; inference can stay on the direct provider.
- Existing `openai_api_direct` provider differs from this contract: inspect before changing; do not append a duplicate TOML table.
Loading
Loading