Documentation for `codex proto` missing
What is the type of issue?
_No response_
What is the issue?
There is no documentation that explains how codex proto should be used.
Where did you find it?
I tried to use codex proto.
This is not helpful:
codex proto -h
Run the Protocol stream via stdin/stdout
Usage: codex proto [OPTIONS]
Options:
-c, --config <key=value> Override a configuration value that would otherwise be loaded from `~/.codex/config.toml`. Use a dotted path (`foo.bar.baz`) to override
nested values. The `value` portion is parsed as JSON. If it fails to parse as JSON, the raw string is used as a literal
-h, --help Print help (see more with '--help')
User story
I want to use codex as an AI Agent to create a paper for Agents4Science. For that i need logs of any input and output including actions. The interactive CLI UI has no option to save such log in the current directory, so i tried to create a wrapper.
I got to a point where the initial prompt is sent just from letting ChatGPT guess the right command from error messages, but then i can't send any additional input. Also, i can't write files and don't have internet access. Parameters seem not to be consistent across modes.
#!/usr/bin/env bash
set -euo pipefail
# ================== INTERNAL PARAMS (your settings kept) ==================
PARAMS=(
-c 'model="gpt-5"'
-c 'tools.web_search=true'
-c 'approval_mode="on-failure"'
-c 'sandbox_permissions=["workspace-write"]'
-c 'sandbox_workspace_write.network_access=true'
)
# ========================================================================
[[ $# -eq 1 ]] || { echo "Usage: $0 <start_prompt.md>" >&2; exit 1; }
PROMPT="$1"
[[ -f "$PROMPT" ]] || { echo "error: prompt not found: $PROMPT" >&2; exit 2; }
codex help 2>/dev/null | grep -qE '(^|[[:space:]])proto([[:space:]]|$)' \
|| { echo "error: 'codex proto' not available" >&2; exit 3; }
mkdir -p logs
TS="$(date +%Y-%m-%dT%H-%M-%S)"
LOG="logs/codex-${TS}.log"
# ---- helpers -------------------------------------------------------------
json_escape() {
sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' \
-e ':a;N;$!ba;s/\r//g' -e ':b;s/\n/\\n/g;tb'
}
mk_id() { printf '%s%04d' "$(date +%s%3N)" "$RANDOM"; }
send_json() { # $1 = raw json line
printf '%s\n' "$1" | tee -a "$LOG" >"$FIFO"
}
make_user_turn() {
printf '{"id":"%s","op":{"type":"user_turn"}}\n' "$(mk_id)"
}
make_user_input() { # $1=text
local esc; esc="$(printf '%s' "$1" | json_escape)"
printf '{"id":"%s","op":{"type":"user_input","items":[{"type":"text","text":"%s"}]}}\n' "$(mk_id)" "$esc"
}
# last call_id from this LOG (prefers latest patch request; falls back to any call_id)
last_call_id() {
# try specific apply_patch_approval_request first
local id
id="$(tac "$LOG" | grep -m1 -o '"apply_patch_approval_request"|"exec_approval_request"' | head -n1 >/dev/null; \
tac "$LOG" | grep -m1 -o '"call_id":"[^"]*"' | head -n1 | sed -E 's/.*"call_id":"([^"]*)".*/\1/')"
printf '%s' "${id:-}"
}
approve_patch_last() { # $1=approved true|false, $2=reason
local cid; cid="$(last_call_id)"
[[ -n "$cid" ]] || { echo "warn: no call_id found in log" | tee -a "$LOG" >&2; return 1; }
local esc; esc="$(printf '%s' "${2:-}" | json_escape)"
send_json "{\"id\":\"$(mk_id)\",\"op\":{\"type\":\"patch_approval\",\"call_id\":\"$cid\",\"approved\":$1,\"reason\":\"$esc\"}}"
}
exec_approval() { # $1=approved true|false, $2=reason (uses last call_id if present)
local cid; cid="$(last_call_id)"
local esc; esc="$(printf '%s' "${2:-}" | json_escape)"
# call_id optional; include if found
if [[ -n "$cid" ]]; then
send_json "{\"id\":\"$(mk_id)\",\"op\":{\"type\":\"exec_approval\",\"approved\":$1,\"reason\":\"$esc\",\"call_id\":\"$cid\"}}"
else
send_json "{\"id\":\"$(mk_id)\",\"op\":{\"type\":\"exec_approval\",\"approved\":$1,\"reason\":\"$esc\"}}"
fi
}
# ---- header log ----------------------------------------------------------
{
echo "=== Codex proto @ ${TS} ==="
echo "cwd: $(pwd)"
echo -n "params:"; printf " %s" "${PARAMS[@]}"; echo
echo "method: proto (JSON lines)"
echo "--- PROMPT begin ---"
cat "$PROMPT"
echo "--- PROMPT end ---"
echo
} >> "$LOG"
# ---- start proto ---------------------------------------------------------
FIFO="$(mktemp -u /tmp/codex_in.XXXXXX)"; mkfifo "$FIFO"
trap 'rm -f "$FIFO"' EXIT INT TERM
stdbuf -oL codex proto "${PARAMS[@]}" <"$FIFO" | tee -a "$LOG" &
PID=$!
# initial prompt: open turn, then send prompt text
RAW_PROMPT="$(cat "$PROMPT")"
printf "%s\n" "$RAW_PROMPT" >> "$LOG"
send_json "$(make_user_input "$RAW_PROMPT")"
echo "[run_codex] proto started. Logging: $LOG"
echo "[run_codex] Type messages; Ctrl-D to end."
echo "[shortcuts] /turn | /approve [reason] | /reject [reason] | /execok [reason] | /execno [reason]"
# interactive loop
while IFS= read -r line </dev/tty; do
# empty -> ignore
[[ -z "$line" ]] && continue
# slash commands
case "$line" in
/turn)
send_json "$(make_user_turn)"
continue
;;
/approve\ *)
reason="${line#"/approve "}"
approve_patch_last true "$reason" || true
continue
;;
/approve)
approve_patch_last true "" || true
continue
;;
/reject\ *)
reason="${line#"/reject "}"
approve_patch_last false "$reason" || true
continue
;;
/reject)
approve_patch_last false "" || true
continue
;;
/execok\ *)
reason="${line#"/execok "}"
exec_approval true "$reason"
continue
;;
/execok)
exec_approval true ""
continue
;;
/execno\ *)
reason="${line#"/execno "}"
exec_approval false "$reason"
continue
;;
/execno)
exec_approval false ""
continue
;;
esac
# normal chat: open turn then send input
printf "HUMAN: %s\n" "$line" >> "$LOG"
send_json "$(make_user_turn)"
send_json "$(make_user_input "$line")"
done
wait "$PID" || true
echo "[run_codex] session closed." >> "$LOG"
My initial prompt is this to test writing files and internet search:
Write a haiku about being an AI Agent scientist and save it to a Markdown file. It should contain the current lottery numbers (6 out of 49).
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗