--- name: codex-setup description: "Initialize sd0x-dev-flow infrastructure for Codex CLI and other non-Claude agents. Generates AGENTS.md, installs the commit-msg hook, copies runner scripts. The pre-push gate is opt-in via --with-push-gate. Use when setting up a new project or after updating skills." allowed-tools: Read, Grep, Glob, Edit, Write, Bash(node:*), Bash(git:*), Bash(ls:*), Bash(mkdir:*), Bash(cp:*), Bash(chmod:*), Bash(bash:*), Bash(cat:*), Bash(wc:*) --- # Codex Setup ## Trigger - Keywords: codex setup, codex init, agents.md, setup codex, initialize codex, codex doctor, codex sync - After: `npx skills add sd0xdev/sd0x-harness` ## Subcommands | Command | Purpose | |---------|---------| | `init` | First-time setup: generate AGENTS.md + install the `commit-msg` hook + copy scripts | | `doctor` | Verify installation integrity: files exist, AGENTS.md hash matches, and each recorded hook is **active** — hook *bytes* are `sync`'s axis, not this one (§ doctor) | | `sync` | Re-generate AGENTS.md + update installed hooks/scripts after skill update | Default (no subcommand): `init` ## Arguments | Flag | Applies to | Effect | |------|-----------|--------| | `--with-push-gate` | `init`, `sync` | Install `pre-push-gate.sh` as the `pre-push` hook. **Off by default** | The `pre-push` gate is the one hook that **waits for a human** — it reads `/dev/tty`, so from a non-interactive context it stalls or fails on a terminal that is not there. That is why it is opt-in, and why every path below reads that choice from state rather than re-deciding it. `commit-msg` stays a default install because it never prompts: it guards the attribution anchor (CLAUDE.md rule 3) by reading the message and deciding, with no `/dev/tty` and no input. **It does still reject** — exit 1 on a policy violation, exit 3 when the policy cannot be evaluated — and it rejects interactive and non-interactive commits alike (`scripts/commit-msg-guard.sh`). The distinction that makes it safe to install by default is *prompts vs. rejects*, not *blocks vs. does not block*. **The flag is the opt-in interface — there is no prompt.** `init` must not ask interactively whether to install the gate: this skill runs under Codex sandboxes and in non-interactive setup flows where an unanswered prompt would either hang or be silently defaulted, and a silent default is exactly what opt-in exists to prevent. ## init ### Phase 1: Detect Host Context 1. Find repo root: `git rev-parse --show-toplevel` 2. Read `package.json` if present → extract `name`, `scripts.test` 3. Read `.claude/CLAUDE.md` or `CLAUDE.md` → extract test command pattern 4. Detect plugin root: find `scripts/build-codex-artifacts.js` relative to this skill ### Phase 2: Generate AGENTS.md Kernel ```bash node /scripts/build-codex-artifacts.js \ --project-dir \ --output /AGENTS.md ``` If the file already exists, warn and ask before overwriting. Verify output: - File exists and is non-empty - Size ≤ 24 KiB (`wc -c < AGENTS.md` ≤ 24576) - No unresolved placeholders (`{PROJECT_NAME}`, `{VERSION}`, `{TEST_COMMAND}`) ### Phase 3: Multi-Mode Hook Install Install the git hooks using priority-ordered detection. The mode detection is identical for both hooks; only *which* hooks are installed differs: | Priority | Condition | Action | |----------|-----------|--------| | 1 | `.husky/` directory exists | Copy the hook's script to `.claude/scripts/`, **then prepend** that hook's executing stanza below to `.husky/` — `commit-msg-guard.sh` into `.husky/commit-msg`, and (only under `--with-push-gate`) `pre-push-gate.sh` into `.husky/pre-push`. **Two stanzas, not one**: they are shaped by what git hands each hook, and § The Husky commit-msg stanza says where they differ | | 2 | `git config core.hooksPath` is set | Install to that path | | 3 | `.git/hooks/` is writable | Direct write | | 4 | Fallback | Write to `.githooks/` + print `git config core.hooksPath .githooks` — **the write alone does not arm the hook**; see below | #### Modes 2–4 write the hook **as** the file, so check who owns it first Mode 1 prepends into a shared container; modes 2–4 put the gate — or the guard — at the resolved hook path **as that file's whole content**. A write there is a delete of whatever was there, and the operator's own `pre-push` may be the only thing standing between them and something this skill knows nothing about. `--with-push-gate` is a request to *add* a guard; taking one away to honour it is not a lesser reading of that request, it is the opposite of it. So before any dedicated-file mode writes a hook, classify the destination — **by content, never by existence**: | Destination | Action | |-------------|--------| | Absent, or present and empty | Write. Nothing is lost | | **sd0x-owned** — one of the first 20 lines is exactly `#