Codex Skill Guide
Operating Contract
- Run
codex --version and codex exec --help first. Stop if Codex is unavailable, and only use flags shown by the installed CLI.
- If the user did not specify a model or reasoning effort, use the installed default. Do not hardcode a model list; model names and supported reasoning levels change over time.
- Select the smallest sandbox needed:
--sandbox read-only for inspection and --sandbox workspace-write for requested local edits. Network access, extra writable roots, and broader modes are separate grants.
- Assemble the command from supported options such as:
-m, --model <MODEL>
--config model_reasoning_effort="<LEVEL>"
--sandbox <read-only|workspace-write|danger-full-access>
-C, --cd <DIR>
--add-dir <DIR>
--json
--ephemeral
--skip-git-repo-check
--dangerously-bypass-approvals-and-sandbox
- Do not use
--skip-git-repo-check by default. Use it only when the user explicitly asks to run outside a Git repository or has approved that boundary bypass for this command.
- Do not use deprecated compatibility shortcuts such as
--full-auto; use the explicit sandbox shown by current help.
- Preserve stderr. Keep it out of the parent context by writing it to a bounded artifact and reading only the exit status, short tail, or targeted diagnostics. Never redirect it to
/dev/null.
- For automation, batch work, cost investigation, or any run that needs measured usage, add
--json and save stdout as JSONL. Read the final usage event and report input, cached input, output, and reasoning tokens when present.
- Enforce a hard wall-clock timeout with the supervising runtime. Stop on non-zero exit or timeout; do not automatically retry an expensive run.
- When continuing a genuinely conversational task, use
codex exec resume --last via stdin. Do not resume a session for homogeneous record batches; start a fresh bounded --ephemeral run per tranche so accumulated history is not resent on every model call.
Safe Prompt Passing
Do not build Codex commands with echo "user prompt" | ...; user text can contain quotes, substitutions, or newlines. Prefer a quoted heredoc so the shell never reinterprets prompt contents:
(
for required_command in python3 head wc mkfifo; do
command -v "$required_command" >/dev/null 2>&1 || {
printf 'Missing required command: %s\n' "$required_command" >&2
exit 127
}
done
codex_skill_dir=${CODEX_SKILL_DIR:-$HOME/.claude/skills/codex}
[ -f "$codex_skill_dir/scripts/run_with_timeout.py" ] || {
printf 'Missing Codex timeout helper: %s\n' \
"$codex_skill_dir/scripts/run_with_timeout.py" >&2
exit 1
}
codex_artifacts=$(mktemp -d) || exit 1
codex_stderr_max_bytes=1048576
codex_stderr_pipe="$codex_artifacts/stderr.pipe"
mkfifo "$codex_stderr_pipe" || exit 1
head -c "$codex_stderr_max_bytes" <"$codex_stderr_pipe" \
>"$codex_artifacts/stderr.log" &
codex_stderr_limiter_pid=$!
if python3 "$codex_skill_dir/scripts/run_with_timeout.py" 1800 \
codex exec resume --last \
2>"$codex_stderr_pipe" <<'EOF'
Your follow-up prompt goes here.
EOF
then
codex_status=0
else
codex_status=$?
fi
stderr_limiter_status=0
wait "$codex_stderr_limiter_pid" || stderr_limiter_status=$?
rm -- "$codex_stderr_pipe" || exit 1
artifact_status=0
stderr_bytes=$(wc -c <"$codex_artifacts/stderr.log") || exit 1
if [ "$stderr_bytes" -ge "$codex_stderr_max_bytes" ]; then
printf 'Codex stderr reached its %s-byte artifact limit\n' \
"$codex_stderr_max_bytes" >&2
artifact_status=125
fi
if [ "$stderr_limiter_status" -ne 0 ]; then artifact_status=$stderr_limiter_status; fi
tail -c 4000 -- "$codex_artifacts/stderr.log"
tail_status=$?
if [ "$codex_status" -eq 0 ] && [ "$artifact_status" -eq 0 ] && [ "$tail_status" -eq 0 ]; then
rm -R -- "$codex_artifacts" || exit $?
else
printf 'Codex artifacts retained: %s\n' "$codex_artifacts" >&2
fi
if [ "$codex_status" -ne 0 ]; then exit "$codex_status"; fi
if [ "$artifact_status" -ne 0 ]; then exit "$artifact_status"; fi
exit "$tail_status"
)
Quick Reference
| Use case |
Sandbox mode |
Key flags |
| Read-only review or analysis |
read-only |
--sandbox read-only |
| Apply local edits |
workspace-write |
--sandbox workspace-write |
| Apply edits that need network access |
workspace-write plus config |
--sandbox workspace-write -c 'sandbox_workspace_write.network_access=true' after approval |
| Machine-readable usage |
Match task |
--json; save JSONL stdout and stderr separately |
| Independent batch tranche |
Match task |
--ephemeral --json; do not resume the previous tranche |
| Permit extra write scope |
Prefer --add-dir |
Ask before adding extra writable directories |
| Permit broad file access |
danger-full-access only after approval |
Ask before adding --sandbox danger-full-access |
| Resume a conversational task |
Inherited from original |
codex exec resume --last via quoted heredoc |
| Run from another directory |
Match task needs |
-C <DIR> plus other flags |
Batch Cost Gate
Before more than one similar model call:
- Define a small calibration ceiling for records, model calls, wall-clock time, and checkpoint cadence; ask for confirmation first when the user has not authorized even that bounded calibration.
- Run one representative calibration tranche with
--json inside that ceiling.
- Measure actual usage from the JSONL event stream; do not estimate from record count alone.
- Project the remaining calls and tokens from the measured tranche.
- State the full-run maximum calls, maximum records, wall-clock budget, and checkpoint cadence.
- Ask for confirmation when the projected full run is materially larger than the calibration or the user did not already authorize that concrete budget.
Stop at every checkpoint if measured usage exceeds the projection. Cached input is still token usage: a high cached-input share usually means the same large prefix or accumulated session context is being sent repeatedly, not that the run is free.
Following Up
- Resume only when prior conversational context is necessary. For independent records, pass only the tranche instructions and compact artifacts needed for that tranche.
- Restate the model, reasoning effort, sandbox, measured usage, and remaining budget before proposing another costly tranche.
- Reaching the requested
done_when condition ends the run. A blocker is not permission to install, upgrade, restart services, migrate or reindex data, edit global config/hooks, write to another repository, or perform GitHub writes unless the current request explicitly authorizes that action.
Error Handling
- Stop and report failures whenever
codex --version or a codex exec command exits non-zero; request direction before retrying.
- Before you use high-impact flags (
--sandbox danger-full-access, --dangerously-bypass-approvals-and-sandbox, --dangerously-bypass-hook-trust, --skip-git-repo-check) ask the user for permission using AskUserQuestion unless it was already given.
- When output includes warnings, partial results, missing usage, or a timeout, preserve the evidence and ask how to adjust. Do not silently degrade to an unmetered or broader run.
Gotchas
--skip-git-repo-check bypasses an important cwd/worktree guard. Treat it like a boundary exception, not a default.
danger-full-access and the --dangerously-* bypass flags are high-impact modes. Prefer read-only, then workspace-write, then modes explicitly listed by the installed CLI, then specific --add-dir grants before considering full access.
- If a prompt came from the user or another model, pass it as stdin or as a single already-quoted CLI argument. Never interpolate it into a shell string.
- Suppressing stderr hides failure and progress evidence; pasting all stderr into the parent wastes context. Save it, then inspect a bounded tail.
- A small output does not imply a cheap run. Repeated large cached prefixes can dominate usage across many short calls.
1---2name: codex-223description: Use when the user asks to run Codex CLI (codex exec, codex resume) or references OpenAI Codex for code analysis, refactoring, or automated editing4---56# Codex Skill Guide78## Operating Contract91. Run `codex --version` and `codex exec --help` first. Stop if Codex is unavailable, and only use flags shown by the installed CLI.102. If the user did not specify a model or reasoning effort, use the installed default. Do not hardcode a model list; model names and supported reasoning levels change over time.113. Select the smallest sandbox needed: `--sandbox read-only` for inspection and `--sandbox workspace-write` for requested local edits. Network access, extra writable roots, and broader modes are separate grants.124. Assemble the command from supported options such as:13 - `-m, --model <MODEL>`14 - `--config model_reasoning_effort="<LEVEL>"`15 - `--sandbox <read-only|workspace-write|danger-full-access>`16 - `-C, --cd <DIR>`17 - `--add-dir <DIR>`18 - `--json`19 - `--ephemeral`20 - `--skip-git-repo-check`21 - `--dangerously-bypass-approvals-and-sandbox`225. Do not use `--skip-git-repo-check` by default. Use it only when the user explicitly asks to run outside a Git repository or has approved that boundary bypass for this command.236. Do not use deprecated compatibility shortcuts such as `--full-auto`; use the explicit sandbox shown by current help.247. Preserve stderr. Keep it out of the parent context by writing it to a bounded artifact and reading only the exit status, short tail, or targeted diagnostics. Never redirect it to `/dev/null`.258. For automation, batch work, cost investigation, or any run that needs measured usage, add `--json` and save stdout as JSONL. Read the final usage event and report input, cached input, output, and reasoning tokens when present.269. Enforce a hard wall-clock timeout with the supervising runtime. Stop on non-zero exit or timeout; do not automatically retry an expensive run.2710. When continuing a genuinely conversational task, use `codex exec resume --last` via stdin. Do not resume a session for homogeneous record batches; start a fresh bounded `--ephemeral` run per tranche so accumulated history is not resent on every model call.2829### Safe Prompt Passing3031Do not build Codex commands with `echo "user prompt" | ...`; user text can contain quotes, substitutions, or newlines. Prefer a quoted heredoc so the shell never reinterprets prompt contents:3233```bash34(35for required_command in python3 head wc mkfifo; do36 command -v "$required_command" >/dev/null 2>&1 || {37 printf 'Missing required command: %s\n' "$required_command" >&238 exit 12739 }40done41codex_skill_dir=${CODEX_SKILL_DIR:-$HOME/.claude/skills/codex}42[ -f "$codex_skill_dir/scripts/run_with_timeout.py" ] || {43 printf 'Missing Codex timeout helper: %s\n' \44 "$codex_skill_dir/scripts/run_with_timeout.py" >&245 exit 146}47codex_artifacts=$(mktemp -d) || exit 148codex_stderr_max_bytes=104857649codex_stderr_pipe="$codex_artifacts/stderr.pipe"50mkfifo "$codex_stderr_pipe" || exit 151head -c "$codex_stderr_max_bytes" <"$codex_stderr_pipe" \52 >"$codex_artifacts/stderr.log" &53codex_stderr_limiter_pid=$!54if python3 "$codex_skill_dir/scripts/run_with_timeout.py" 1800 \55 codex exec resume --last \56 2>"$codex_stderr_pipe" <<'EOF'57Your follow-up prompt goes here.58EOF59then60 codex_status=061else62 codex_status=$?63fi64stderr_limiter_status=065wait "$codex_stderr_limiter_pid" || stderr_limiter_status=$?66rm -- "$codex_stderr_pipe" || exit 167artifact_status=068stderr_bytes=$(wc -c <"$codex_artifacts/stderr.log") || exit 169if [ "$stderr_bytes" -ge "$codex_stderr_max_bytes" ]; then70 printf 'Codex stderr reached its %s-byte artifact limit\n' \71 "$codex_stderr_max_bytes" >&272 artifact_status=12573fi74if [ "$stderr_limiter_status" -ne 0 ]; then artifact_status=$stderr_limiter_status; fi75tail -c 4000 -- "$codex_artifacts/stderr.log"76tail_status=$?77if [ "$codex_status" -eq 0 ] && [ "$artifact_status" -eq 0 ] && [ "$tail_status" -eq 0 ]; then78 rm -R -- "$codex_artifacts" || exit $?79else80 printf 'Codex artifacts retained: %s\n' "$codex_artifacts" >&281fi82if [ "$codex_status" -ne 0 ]; then exit "$codex_status"; fi83if [ "$artifact_status" -ne 0 ]; then exit "$artifact_status"; fi84exit "$tail_status"85)86```8788### Quick Reference89| Use case | Sandbox mode | Key flags |90| --- | --- | --- |91| Read-only review or analysis | `read-only` | `--sandbox read-only` |92| Apply local edits | `workspace-write` | `--sandbox workspace-write` |93| Apply edits that need network access | `workspace-write` plus config | `--sandbox workspace-write -c 'sandbox_workspace_write.network_access=true'` after approval |94| Machine-readable usage | Match task | `--json`; save JSONL stdout and stderr separately |95| Independent batch tranche | Match task | `--ephemeral --json`; do not resume the previous tranche |96| Permit extra write scope | Prefer `--add-dir` | Ask before adding extra writable directories |97| Permit broad file access | `danger-full-access` only after approval | Ask before adding `--sandbox danger-full-access` |98| Resume a conversational task | Inherited from original | `codex exec resume --last` via quoted heredoc |99| Run from another directory | Match task needs | `-C <DIR>` plus other flags |100101## Batch Cost Gate102103Before more than one similar model call:1041051. Define a small calibration ceiling for records, model calls, wall-clock time, and checkpoint cadence; ask for confirmation first when the user has not authorized even that bounded calibration.1062. Run one representative calibration tranche with `--json` inside that ceiling.1073. Measure actual usage from the JSONL event stream; do not estimate from record count alone.1084. Project the remaining calls and tokens from the measured tranche.1095. State the full-run maximum calls, maximum records, wall-clock budget, and checkpoint cadence.1106. Ask for confirmation when the projected full run is materially larger than the calibration or the user did not already authorize that concrete budget.111112Stop at every checkpoint if measured usage exceeds the projection. Cached input is still token usage: a high cached-input share usually means the same large prefix or accumulated session context is being sent repeatedly, not that the run is free.113114## Following Up115- Resume only when prior conversational context is necessary. For independent records, pass only the tranche instructions and compact artifacts needed for that tranche.116- Restate the model, reasoning effort, sandbox, measured usage, and remaining budget before proposing another costly tranche.117- Reaching the requested `done_when` condition ends the run. A blocker is not permission to install, upgrade, restart services, migrate or reindex data, edit global config/hooks, write to another repository, or perform GitHub writes unless the current request explicitly authorizes that action.118119## Error Handling120- Stop and report failures whenever `codex --version` or a `codex exec` command exits non-zero; request direction before retrying.121- Before you use high-impact flags (`--sandbox danger-full-access`, `--dangerously-bypass-approvals-and-sandbox`, `--dangerously-bypass-hook-trust`, `--skip-git-repo-check`) ask the user for permission using AskUserQuestion unless it was already given.122- When output includes warnings, partial results, missing usage, or a timeout, preserve the evidence and ask how to adjust. Do not silently degrade to an unmetered or broader run.123124## Gotchas125126- `--skip-git-repo-check` bypasses an important cwd/worktree guard. Treat it like a boundary exception, not a default.127- `danger-full-access` and the `--dangerously-*` bypass flags are high-impact modes. Prefer `read-only`, then `workspace-write`, then modes explicitly listed by the installed CLI, then specific `--add-dir` grants before considering full access.128- If a prompt came from the user or another model, pass it as stdin or as a single already-quoted CLI argument. Never interpolate it into a shell string.129- Suppressing stderr hides failure and progress evidence; pasting all stderr into the parent wastes context. Save it, then inspect a bounded tail.130- A small output does not imply a cheap run. Repeated large cached prefixes can dominate usage across many short calls.