From 36192dd2a6e0d58f6261779247acd39a8e0b9bd9 Mon Sep 17 00:00:00 2001 From: oz6un Date: Tue, 14 Jul 2026 06:30:22 +0300 Subject: [PATCH] feat: optional OpenAI Codex CLI install (INSTALL_CODEX, off by default) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an opt-in so rebuilds can install Codex CLI alongside Claude Code without changing the repo's Claude-Code-first identity. INSTALL_CODEX (secrets.env, empty/0 by default) → setup-user stages a normalized 0/1 flag → remote-setup installs @openai/codex (npm, npm already on PATH from the node section) plus bubblewrap (its Linux sandbox), both guarded for idempotency. Auth stays a separate one-time 'codex login' (documented in the README auth table). Adversarial review refuted all six attack surfaces (npm-on-PATH, case-redirect fail-direction, set -e OR-chain safety, staged-file shipping, default-off, residue); fresh-install path verified live by uninstalling codex and re-running setup (reinstalled + auth intact + real turn). Co-Authored-By: Claude Fable 5 --- README.md | 3 ++- files/remote-setup.sh | 11 +++++++++++ secrets.env.example | 5 +++++ setup-user.sh | 2 ++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d49730..b1c6a5b 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ manage, wired for Claude Code — and rebuild the whole thing from this repo in - **Tailnet-only.** Zero public TCP ports. Access is Tailscale SSH: your tailnet identity is the credential. - **Hardened and self-maintaining.** UFW default-deny, key-only sshd, automatic security patches with a nightly reboot window. - **Self-alerting.** Pushes to your phone when the disk fills or a service fails. -- **Ready for development.** fish + starship, persistent tmux, Node/pnpm, Docker, Claude Code with configurable skills and phone notifications. +- **Ready for development.** fish + starship, persistent tmux, Node/pnpm, Docker, Claude Code with configurable skills and phone notifications (and OpenAI Codex CLI, optional). - **Instant previews.** `http://devbox:` reaches any dev server or container on the box — even one bound to localhost. ```mermaid @@ -74,6 +74,7 @@ Three logins happen in your browser and can't be scripted. Do them once per box: |---|---|---| | `gh auth login` | on devbox | GitHub device flow — gives the box its own revocable token | | `claude` → login | on devbox | Claude subscription OAuth | +| `codex login` → login | on devbox | OpenAI ChatGPT OAuth — only if `INSTALL_CODEX=1` | | Disable key expiry | [Tailscale admin](https://login.tailscale.com/admin/machines) → devbox → ⋯ | Keeps the node key (and thus SSH) from expiring in ~180 days | Set up the Pushover app and account to receive notifications (keys go in `secrets.env`), diff --git a/files/remote-setup.sh b/files/remote-setup.sh index ebfbf40..ac1bcef 100755 --- a/files/remote-setup.sh +++ b/files/remote-setup.sh @@ -55,6 +55,17 @@ while IFS= read -r skill_url; do fi done < "$S/claude-skills" +# Optional: OpenAI Codex CLI (npm) + bubblewrap (its Linux sandbox). npm is on +# PATH from the node section above. Auth is a separate one-time `codex login`. +if [ "$(cat "$S/install-codex" 2>/dev/null)" = 1 ]; then + echo "== codex cli (optional) ==" + command -v codex >/dev/null || npm install -g @openai/codex >/dev/null 2>&1 \ + || echo "WARN: codex install failed" + command -v bwrap >/dev/null \ + || sudo DEBIAN_FRONTEND=noninteractive apt-get -yq install bubblewrap >/dev/null 2>&1 \ + || echo "WARN: bubblewrap install failed (codex falls back to a bundled copy)" +fi + echo "== health-check timer (root systemd, hourly) ==" sudo install -m 700 -o root -g root "$S/devbox-health" /usr/local/bin/devbox-health sudo tee /etc/systemd/system/devbox-health.service >/dev/null <<'UNIT' diff --git a/secrets.env.example b/secrets.env.example index ab8de15..5cf31ef 100644 --- a/secrets.env.example +++ b/secrets.env.example @@ -29,6 +29,11 @@ PUSHOVER_USER= # CLAUDE_SKILLS="https://github.com/you/your-skill.git" CLAUDE_SKILLS= +# Also install OpenAI's Codex CLI alongside Claude Code (optional; off by default). +# Set to 1 to install it + bubblewrap (its Linux sandbox). Auth is a separate +# one-time `codex login` on the box (see README). +INSTALL_CODEX= + # Regex of ~/Code paths sync-code.sh should skip (optional). # SYNC_EXCLUDE_RE="third-party-audits|scratch" SYNC_EXCLUDE_RE= diff --git a/setup-user.sh b/setup-user.sh index 61ccf2a..b131067 100755 --- a/setup-user.sh +++ b/setup-user.sh @@ -45,6 +45,8 @@ sed -e "s|__DEV_USER__|$DEV_USER|g" files/claude-settings.json > "$staging/claud printf '%s' "${GIT_NAME:-}" > "$staging/git-name" printf '%s' "${GIT_EMAIL:-}" > "$staging/git-email" echo "${CLAUDE_SKILLS:-}" | tr ' \t' '\n' | grep -v '^$' > "$staging/claude-skills" || true +# Normalize the codex opt-in to 0/1 for the remote script. +case "${INSTALL_CODEX:-0}" in 1|true|yes|on) echo 1 ;; *) echo 0 ;; esac > "$staging/install-codex" # COPYFILE_DISABLE stops macOS bsdtar from embedding AppleDouble (._*) junk. COPYFILE_DISABLE=1 tar czf - -C "$staging" . | ssh "$DEV_USER@$DEVBOX_NAME" \