I mean, if you take out the guard rails, here's codex in 46 lines of bash:
#!/usr/bin/env bash
set -euo pipefail
# Fail fast if OPENAI_API_KEY is unset or empty
: "${OPENAI_API_KEY:?set OPENAI_API_KEY}"
MODEL="${MODEL:-gpt-5.2-chat-latest}"
extract_text_joined() {
# Collect all text fields from the Responses API output and join them
jq -r '[.output[]?.content[]? | select(has("text")) | .text] | join("")'
}
apply_writes() {
local plan="$1"
echo "$plan" | jq -c '.files[]' | while read -r f; do
local path content
path="$(echo "$f" | jq -r '.path')"
content="$(echo "$f" | jq -r '.content')"
mkdir -p "$(dirname "$path")"
printf "%s" "$content" > "$path"
echo "wrote $path"
done
}
while true; do
printf "> "
read -r USER_INPUT || exit 0
[[ -z "$USER_INPUT" ]] && continue
# File list relative to cwd
TREE="$(find . -type f -maxdepth 6 -print | sed 's|^\./||')"
USER_JSON="$(jq -n --arg task "$USER_INPUT" --arg tree "$TREE" \
'{task:$task, workspace_tree:$tree,
rules:[
"Return ONLY JSON matching the schema.",
"Write files wholesale: full final content for each file.",
"If no file changes are needed, return files:[]"
] }')"
RESP="$(
curl -s https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg model "$MODEL" --argjson user "$USER_JSON" '{model:$model,input:[{role:"system",content:"You output only JSON file-write plans."},{role:"user",content:$user}],text:{format:{type:"json_schema",name:"file_writes",schema:{type:"object",additionalProperties:false,properties:{files:{type:"array",items:{type:"object",additionalProperties:false,properties:{path:{type:"string"},content:{type:"string"}},required:["path","content"]}}},required:["files"]}}}')"
)"
PLAN="$(printf "%s" "$RESP" | extract_text_joined)"
apply_writes "$PLAN"
done