界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
开发与工程 · SKILL.md

codex-on-ish

codex-on-ish

【开发与工程】Install and run OpenAI Codex CLI inside the Minis/iSH Alpine sandbox on iOS, where rustls TLS and async sockets are broken. Covers the local MITM proxy with P-256 certs, version-spoofing to unlock newer models (gpt-5.6 family), forcing SSE instead of websockets, ChatGPT device-auth login driven by curl, and the refcounted proxy wrapper. Use when the …

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: codex-on-ish description: Install and run OpenAI Codex CLI inside the Minis/iSH Alpine sandbox on iOS, where rustls TLS and async sockets are broken. Covers the local MITM proxy with P-256 certs, version-spoofing to unlock newer models (gpt-5.6 family), forcing SSE instead of websockets, ChatGPT device-auth login driven by curl, and the refcounted proxy wrapper. Use when the user wants Codex or other Rust-based AI CLIs on the iPhone/iPad Minis shell, or hits "error sending request", "must support ECDSA_NISTP521_SHA512" panics, model "requires a newer version of Codex", or npm errno 65 inside iSH.

Codex on iSH (Minis iOS sandbox)

Run the OpenAI Codex CLI natively in the Alpine/iSH environment. Works around the platform's broken Rust networking stack with a local MITM proxy.

Why this is needed (the two bugs)

  1. rustls misbehaves on iSH's translated CPU. Official musl binaries ≥ v0.143 panic at the first TLS handshake (installed rustls crypto provider must support ECDSA_NISTP521_SHA512) because aws-lc-rs CPU detection fails in the emulator. v0.130 (ring provider) handshakes, but ONLY with ECDSA P-256 certificates — RSA and P-521 get refused.
  2. Async sockets to remote hosts fail (connect errno 65 / reqwest error sending request). Blocking-socket clients (curl, Python) work fine; loopback connections work fine. Routing Rust traffic through a local proxy converts the hostile leg into a reliable one.

Both bugs are iSH-specific. Termux forks do NOT fix them (verified: their rustls code is identical to upstream).

Install

sh scripts/setup.sh

This downloads codex v0.130.0 musl aarch64, generates the P-256 CA/server certs, installs pyproxy6.py (proxy) and the codex wrapper into /usr/local/bin, and writes ~/.codex/config.toml defaults (model, yolo approval policy).

Login (ChatGPT account)

Codex's own login flows die within minutes (iOS kills the app at 48 CPU-s/min in background), so drive the OAuth device flow with curl instead:

sh scripts/token_poller3.sh &     # prints a live user_code, auto-renews
# user visits https://auth.openai.com/codex/device, enters the code
# poller exchanges the artifact and writes /tmp/token_result.json
sh scripts/write_auth_json.sh     # installs ~/.codex/auth.json
codex login status                # -> "Logged in using ChatGPT"

Key protocol facts (see references/auth-protocol.md):

  • POST /api/accounts/deviceauth/usercode JSON {client_id} → device_auth_id + user_code
  • poll /deviceauth/token with {device_auth_id, client_id, user_code} until it returns authorization_code + code_verifier
  • exchange at /oauth/token form-encoded (JSON is rejected) with redirect_uri=https://auth.openai.com/deviceauth/callback → id/access/refresh tokens
  • Python urllib is blocked by Cloudflare on these endpoints — always use curl.

What the wrapper does

codex (wrapper) registers a refcount file, starts the proxy as a singleton (pidfile + pgrep guard), waits for the port, execs codex.bin with SSL_CERT_FILE/HTTPS_PROXY env, and cleans up on exit. The proxy tears itself down ~8 s after the last client leaves. Output is silent; logs live in /tmp/codex-proxy/.

Model gating and the version spoof

The backend gates models by reported client version (e.g. gpt-5.6-* requires ≥ 0.144.0 — the exact versions that panic on iSH). The proxy rewrites 0.130.0 → 0.151.0 in-flight (same byte length, so HTTP framing survives) in the request line, version: header, and bodies.

It also down-translates the models catalog: drops max/ultra reasoning efforts v0.130 can't parse, forces prefer_websockets=false, and rewrites Content-Length. Websocket upgrades on /backend-api/codex/responses get a local 501 so codex falls back to SSE (WS frames would stall the HTTP-framed relay); other WS upgrades pass through raw.

Troubleshooting

See references/troubleshooting.md for: cert re-generation, DNS EAI_AGAIN retries, "models list failed to refresh", login poller death, upstream 502s, and the iOS background CPU-budget kills.

我的收藏