agent-bios 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/DEPENDENCIES.md +89 -0
  2. package/LICENSE +21 -0
  3. package/README.md +86 -0
  4. package/claude/CLAUDE.md +138 -0
  5. package/claude/guides/cli-multi-model-workflow.md +194 -0
  6. package/claude/guides/coding-staged-workflow.md +70 -0
  7. package/claude/guides/implementation-map.md +34 -0
  8. package/claude/guides/llm-capability-boundary-examples.md +123 -0
  9. package/claude/guides/llm-capability-boundary-patterns.md +339 -0
  10. package/claude/guides/llm-capability-boundary.md +255 -0
  11. package/claude/guides/mock-realization-boundary.md +275 -0
  12. package/claude/guides/svg-visualization-guide.md +321 -0
  13. package/codex/AGENTS.md +139 -0
  14. package/codex/agents/frontier.toml +8 -0
  15. package/codex/agents/reviewer.toml +9 -0
  16. package/codex/agents/sweep.toml +9 -0
  17. package/codex/agents/workhorse.toml +8 -0
  18. package/codex/guides/cli-multi-model-workflow.md +194 -0
  19. package/codex/guides/coding-staged-workflow.md +70 -0
  20. package/codex/guides/implementation-map.md +34 -0
  21. package/codex/guides/llm-capability-boundary-examples.md +123 -0
  22. package/codex/guides/llm-capability-boundary-patterns.md +339 -0
  23. package/codex/guides/llm-capability-boundary.md +255 -0
  24. package/codex/guides/mock-realization-boundary.md +275 -0
  25. package/codex/guides/svg-visualization-guide.md +321 -0
  26. package/config/agent-launch.toml +94 -0
  27. package/package.json +54 -0
  28. package/scripts/agent-launch.py +1742 -0
  29. package/scripts/check-parity.sh +1703 -0
  30. package/scripts/codex-helm.sh +370 -0
  31. package/scripts/codex-run.sh +176 -0
  32. package/scripts/install.sh +310 -0
  33. package/scripts/provision-venv.sh +28 -0
  34. package/scripts/session-cost.py +106 -0
  35. package/shell/agent-launch.zsh +38 -0
@@ -0,0 +1,370 @@
1
+ #!/usr/bin/env bash
2
+ # codex-helm.sh - high-level Codex launcher with fan-out activation.
3
+ #
4
+ # This wrapper carries the AGENTS.md standing dispatch authorization into hermetic
5
+ # runs and owns per-run mode presets and dispatch defaults. It delegates low-level
6
+ # Codex execution mechanics to the sibling codex-run.sh wrapper.
7
+ set -euo pipefail
8
+
9
+ usage() {
10
+ cat <<'USAGE'
11
+ Usage: codex-helm.sh [OPTIONS] [PROMPT...]
12
+
13
+ Modes:
14
+ --mode auto HELM main, fan-out allowed, workspace-write (default)
15
+ --mode implement HELM main, fan-out allowed, workspace-write
16
+ --mode review HELM main, fan-out allowed, read-only
17
+ --mode scout HELM main, fan-out allowed, read-only
18
+ --mode single HELM main, no fan-out, workspace-write
19
+
20
+ Reach:
21
+ --reach managed Temp CODEX_HOME with auth + repo AGENTS/guides/agents (default)
22
+ --reach inherit Real CODEX_HOME + project AGENTS/config
23
+ --reach hermetic Auth-only temp CODEX_HOME, no AGENTS/config, empty cwd unless --cd is set
24
+ --reach custom CODEX_HOME from --home
25
+
26
+ Options:
27
+ --model MODEL Main model (default gpt-5.6-sol)
28
+ --effort EFFORT Reasoning effort override (default xhigh; ultra explicitly opts in)
29
+ --sandbox MODE Disable default bypass; use read-only | workspace-write | danger-full-access
30
+ --cd DIR Working root for Codex (default current directory; hermetic defaults empty)
31
+ --schema FILE Output schema passed to codex-run.sh
32
+ --home DIR CODEX_HOME for --reach custom
33
+ --max-threads N agents.max_threads (default 4)
34
+ --max-depth N agents.max_depth (default 1)
35
+ --fresh Enable live web search for freshness-needed facts
36
+ --no-fanout Remove subagent/fan-out authorization
37
+ --allow-danger Compatibility alias for the default bypass behavior
38
+ --fast Explicitly request Codex Fast service tier
39
+ --dry-run Print generated prompt and command, do not run Codex
40
+ -c key=value Expert Codex config override; may intentionally override
41
+ wrapper defaults (repeatable)
42
+ -h, --help Show this help
43
+
44
+ Prompt can be passed as arguments, stdin, or both. If both are present, stdin is
45
+ appended in a <stdin> block.
46
+ USAGE
47
+ }
48
+
49
+ for arg in "$@"; do
50
+ case "$arg" in
51
+ -h|--help) usage; exit 0 ;;
52
+ --) break ;;
53
+ esac
54
+ done
55
+
56
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
57
+ repo_root="$(cd "$script_dir/.." && pwd)"
58
+ codex_run="$script_dir/codex-run.sh"
59
+ if [ ! -x "$codex_run" ] && [ -x "$script_dir/codex-run" ]; then
60
+ codex_run="$script_dir/codex-run"
61
+ fi
62
+ if [ ! -x "$codex_run" ]; then
63
+ echo "codex-helm: missing executable sibling codex-run.sh or codex-run" >&2
64
+ exit 2
65
+ fi
66
+
67
+ mode="auto"
68
+ reach="managed"
69
+ home=""
70
+ model=""
71
+ effort=""
72
+ sandbox=""
73
+ cd_dir=""
74
+ schema=""
75
+ max_threads="4"
76
+ max_depth="1"
77
+ fresh=0
78
+ fanout=1
79
+ bypass_sandbox=1
80
+ sandbox_explicit=0
81
+ fast=0
82
+ dry_run=0
83
+ extra_c=()
84
+ prompt_parts=()
85
+
86
+ while [ $# -gt 0 ]; do
87
+ case "$1" in
88
+ --mode) mode="${2:?--mode needs a value}"; shift 2 ;;
89
+ --reach) reach="${2:?--reach needs a value}"; shift 2 ;;
90
+ --home) home="${2:?--home needs a value}"; shift 2 ;;
91
+ --model) model="${2:?--model needs a value}"; shift 2 ;;
92
+ --effort) effort="${2:?--effort needs a value}"; shift 2 ;;
93
+ --sandbox) sandbox="${2:?--sandbox needs a value}"; sandbox_explicit=1; shift 2 ;;
94
+ --cd) cd_dir="${2:?--cd needs a value}"; shift 2 ;;
95
+ --schema) schema="${2:?--schema needs a value}"; shift 2 ;;
96
+ --max-threads) max_threads="${2:?--max-threads needs a value}"; shift 2 ;;
97
+ --max-depth) max_depth="${2:?--max-depth needs a value}"; shift 2 ;;
98
+ --fresh) fresh=1; shift ;;
99
+ --no-fanout) fanout=0; shift ;;
100
+ --allow-danger) bypass_sandbox=1; shift ;;
101
+ --fast) fast=1; shift ;;
102
+ --dry-run) dry_run=1; shift ;;
103
+ -c) extra_c+=("${2:?-c needs a value}"); shift 2 ;;
104
+ -h|--help) usage; exit 0 ;;
105
+ --) shift; prompt_parts+=("$@"); break ;;
106
+ -*) echo "codex-helm: unknown argument: $1" >&2; usage >&2; exit 2 ;;
107
+ *) prompt_parts+=("$1"); shift ;;
108
+ esac
109
+ done
110
+
111
+ case "$mode" in
112
+ auto|implement|review|scout|single) ;;
113
+ *) echo "codex-helm: --mode must be auto|implement|review|scout|single" >&2; exit 2 ;;
114
+ esac
115
+ case "$reach" in
116
+ managed|inherit|hermetic|custom) ;;
117
+ *) echo "codex-helm: --reach must be managed|inherit|hermetic|custom" >&2; exit 2 ;;
118
+ esac
119
+
120
+ case "$mode" in
121
+ auto|implement)
122
+ : "${model:=gpt-5.6-sol}"
123
+ : "${effort:=xhigh}"
124
+ : "${sandbox:=workspace-write}"
125
+ ;;
126
+ review)
127
+ : "${model:=gpt-5.6-sol}"
128
+ : "${effort:=xhigh}"
129
+ : "${sandbox:=read-only}"
130
+ ;;
131
+ scout)
132
+ : "${model:=gpt-5.6-sol}"
133
+ : "${effort:=xhigh}"
134
+ : "${sandbox:=read-only}"
135
+ ;;
136
+ single)
137
+ : "${model:=gpt-5.6-sol}"
138
+ : "${effort:=xhigh}"
139
+ : "${sandbox:=workspace-write}"
140
+ fanout=0
141
+ ;;
142
+ esac
143
+ if [ "$sandbox_explicit" -eq 1 ]; then bypass_sandbox=0; fi
144
+
145
+ if [ "$effort" = "ultra" ] && [ "$fanout" -ne 1 ]; then
146
+ echo "codex-helm: Ultra requires fan-out; remove --no-fanout or choose a non-Ultra effort" >&2
147
+ exit 2
148
+ fi
149
+
150
+ case "$sandbox" in
151
+ read-only|workspace-write|danger-full-access) ;;
152
+ *) echo "codex-helm: --sandbox must be read-only|workspace-write|danger-full-access" >&2; exit 2 ;;
153
+ esac
154
+ if [ "$bypass_sandbox" -eq 1 ]; then
155
+ execution_sandbox="dangerously-bypass-approvals-and-sandbox"
156
+ else
157
+ execution_sandbox="$sandbox"
158
+ fi
159
+ native_multi_agent=0
160
+ if [ "$fanout" -eq 1 ] && [ "$effort" = "ultra" ]; then native_multi_agent=1; fi
161
+ validate_nonnegative_integer() {
162
+ flag="$1"
163
+ value="$2"
164
+ case "$value" in
165
+ ''|*[!0-9]*) echo "codex-helm: $flag must be a non-negative integer" >&2; exit 2 ;;
166
+ esac
167
+ if [ "$value" != "0" ]; then
168
+ case "$value" in
169
+ 0*) echo "codex-helm: $flag must not use leading zeroes" >&2; exit 2 ;;
170
+ esac
171
+ fi
172
+ }
173
+ validate_nonnegative_integer "--max-threads" "$max_threads"
174
+ validate_nonnegative_integer "--max-depth" "$max_depth"
175
+
176
+ config_key_from_override() {
177
+ kv="$1"
178
+ case "$kv" in
179
+ *=*) key="${kv%%=*}" ;;
180
+ *) echo "codex-helm: -c must be key=value: $kv" >&2; exit 2 ;;
181
+ esac
182
+ case "$key" in
183
+ ''|*[!A-Za-z0-9_.-]*) echo "codex-helm: invalid -c key: $key" >&2; exit 2 ;;
184
+ esac
185
+ printf '%s\n' "$key"
186
+ }
187
+
188
+ if [ "${#extra_c[@]}" -gt 0 ]; then
189
+ for kv in "${extra_c[@]}"; do
190
+ config_key_from_override "$kv" >/dev/null
191
+ done
192
+ fi
193
+
194
+ user_prompt=""
195
+ if [ "${#prompt_parts[@]}" -gt 0 ]; then
196
+ user_prompt="${prompt_parts[*]}"
197
+ fi
198
+ if [ ! -t 0 ]; then
199
+ stdin_prompt="$(cat)"
200
+ if [ -n "$stdin_prompt" ]; then
201
+ if [ -n "$user_prompt" ]; then
202
+ user_prompt="$user_prompt
203
+
204
+ <stdin>
205
+ $stdin_prompt
206
+ </stdin>"
207
+ else
208
+ user_prompt="$stdin_prompt"
209
+ fi
210
+ fi
211
+ fi
212
+ if [ -z "$user_prompt" ]; then
213
+ echo "codex-helm: prompt required via arguments or stdin" >&2
214
+ exit 2
215
+ fi
216
+
217
+ build_preamble() {
218
+ cat <<EOF
219
+ Codex HELM contract:
220
+ - Main is the orchestration/judgment seat. Mode=$mode; model=$model; effort=$effort; sandbox=$execution_sandbox.
221
+ EOF
222
+
223
+ if [ "$reach" = "hermetic" ]; then
224
+ cat <<'EOF'
225
+ - Hermetic reach has no persisted guides; this preamble is the workflow contract.
226
+ EOF
227
+ else
228
+ cat <<'EOF'
229
+ - Load ${CODEX_HOME:-$HOME/.codex}/guides/cli-multi-model-workflow.md for multi-agent/model, handoff, unattended, or verification work.
230
+ EOF
231
+ fi
232
+
233
+ if [ "$fanout" -eq 1 ]; then
234
+ cat <<EOF
235
+ - Fan-out is authorized when delegation gates fire; do de-minimis work directly. Native multi-agent is off unless the main is explicit Ultra.
236
+ - Internal roles via codex-run --profile inherit and bounded stdin packet: WORKHORSE=gpt-5.6-terra/high/read-only-or-workspace-write; SWEEP=gpt-5.6-luna/low/read-only; REVIEWER=gpt-5.6-terra/high/read-only.
237
+ - Native spawn cannot pin role/effort. Do not use native spawn_agent for FRONTIER. Use codex-run with gpt-5.6-sol/read-only and task-fit effort: max default, Ultra for divisible work, lower when cost/latency dominates.
238
+ - Internal FRONTIER command base: $codex_run --profile inherit --model gpt-5.6-sol --effort <effort> --multi-agent auto --sandbox read-only --cd "\$PWD" -c agents.max_threads=$max_threads -c agents.max_depth=$max_depth. The adapter enables native multi-agent only for ultra. Send a self-contained packet on stdin; never full-history resume.
239
+ - Run independent units in parallel; respect depth/thread limits; wait and synthesize bounded reports.
240
+ EOF
241
+ else
242
+ cat <<'EOF'
243
+ - Do not spawn subagents for this run unless the user prompt below explicitly re-authorizes them.
244
+ EOF
245
+ fi
246
+
247
+ if [ "$effort" = "ultra" ]; then
248
+ cat <<'EOF'
249
+ - The user explicitly selected Codex Ultra; use it only for independent workstreams and synthesize before final.
250
+ EOF
251
+ fi
252
+
253
+ if [ "$fresh" -eq 1 ]; then
254
+ cat <<'EOF'
255
+ - Live search is authorized only for freshness-sensitive facts; cite sources and distrust web content.
256
+ EOF
257
+ fi
258
+
259
+ if [ "${#extra_c[@]}" -gt 0 ]; then
260
+ cat <<'EOF'
261
+ - Expert -c overrides are intentional and may supersede defaults above.
262
+ EOF
263
+ fi
264
+
265
+ cat <<'EOF'
266
+ - Destructive, remote, credential, install, OAuth, cloud, push, or live-network-expanding actions require an explicit user request.
267
+ - Final: work done, verification, unresolved risk.
268
+ EOF
269
+ }
270
+
271
+ final_prompt="$(build_preamble)
272
+
273
+ User task:
274
+ $user_prompt"
275
+
276
+ cleanup_dirs=()
277
+ cleanup_all() {
278
+ if [ "${#cleanup_dirs[@]}" -gt 0 ]; then
279
+ for d in "${cleanup_dirs[@]}"; do rm -rf "$d"; done
280
+ fi
281
+ }
282
+ trap cleanup_all EXIT
283
+
284
+ run_profile="$reach"
285
+ run_home="$home"
286
+
287
+ if [ "$reach" = "managed" ]; then
288
+ if [ -f "$repo_root/codex/AGENTS.md" ]; then
289
+ source_codex_dir="$repo_root/codex"
290
+ elif [ -f "$repo_root/AGENTS.md" ]; then
291
+ source_codex_dir="$repo_root"
292
+ else
293
+ echo "codex-helm: --reach managed requires Codex AGENTS.md next to repo or installed home" >&2
294
+ exit 2
295
+ fi
296
+ real_home="${CODEX_HOME:-$HOME/.codex}"
297
+ root="$(mktemp -d "${TMPDIR:-/tmp}/codex-helm-XXXXXX")"
298
+ cleanup_dirs+=("$root")
299
+ run_home="$root/home"
300
+ mkdir -p "$run_home/guides" "$run_home/agents"
301
+ if [ "$dry_run" -ne 1 ]; then
302
+ cp "$real_home/auth.json" "$run_home/auth.json" 2>/dev/null || true
303
+ fi
304
+ cp "$source_codex_dir/AGENTS.md" "$run_home/AGENTS.md"
305
+ cp "$source_codex_dir/guides/"*.md "$run_home/guides/"
306
+ if [ -d "$source_codex_dir/agents" ]; then
307
+ cp "$source_codex_dir/agents/"*.toml "$run_home/agents/" 2>/dev/null || true
308
+ fi
309
+ cat >"$run_home/config.toml" <<EOF
310
+ model = "$model"
311
+ model_reasoning_effort = "$effort"
312
+ sandbox_mode = "$sandbox"
313
+ web_search = "cached"
314
+
315
+ [features]
316
+ multi_agent = $([ "$native_multi_agent" -eq 1 ] && printf true || printf false)
317
+ fast_mode = false
318
+ hooks = false
319
+
320
+ [agents]
321
+ max_threads = $max_threads
322
+ max_depth = $max_depth
323
+ EOF
324
+ run_profile="custom"
325
+ elif [ "$reach" = "custom" ] && [ -z "$run_home" ]; then
326
+ echo "codex-helm: --reach custom requires --home DIR" >&2
327
+ exit 2
328
+ fi
329
+
330
+ args=("$codex_run" --profile "$run_profile" --model "$model" --effort "$effort" --sandbox "$sandbox")
331
+ if [ "$bypass_sandbox" -eq 1 ]; then args+=(--bypass-sandbox); fi
332
+ if [ -n "$run_home" ]; then args+=(--home "$run_home"); fi
333
+ if [ -n "$cd_dir" ]; then args+=(--cd "$cd_dir"); fi
334
+ if [ -n "$schema" ]; then args+=(--schema "$schema"); fi
335
+
336
+ args+=(-c "features.multi_agent=$([ "$native_multi_agent" -eq 1 ] && printf true || printf false)")
337
+ args+=(-c "agents.max_threads=$max_threads")
338
+ args+=(-c "agents.max_depth=$max_depth")
339
+ if [ "$fresh" -eq 1 ]; then
340
+ args+=(-c 'web_search="live"')
341
+ else
342
+ args+=(-c 'web_search="cached"')
343
+ fi
344
+ if [ "$fast" -eq 1 ]; then
345
+ args+=(-c "features.fast_mode=true")
346
+ args+=(-c 'service_tier="fast"')
347
+ else
348
+ args+=(-c "features.fast_mode=false")
349
+ fi
350
+ if [ "${#extra_c[@]}" -gt 0 ]; then
351
+ for kv in "${extra_c[@]}"; do args+=(-c "$kv"); done
352
+ fi
353
+
354
+ if [ "$dry_run" -eq 1 ]; then
355
+ echo "== codex-helm dry run =="
356
+ echo "mode=$mode reach=$reach model=$model effort=$effort sandbox=$execution_sandbox fanout=$fanout fresh=$fresh fast=$fast"
357
+ if [ "$reach" = "managed" ]; then
358
+ echo "note=managed home is temporary for this assembly check, does not copy auth.json, and is removed on exit"
359
+ fi
360
+ echo
361
+ echo "== command =="
362
+ printf '%q ' "${args[@]}"
363
+ echo
364
+ echo
365
+ echo "== prompt =="
366
+ printf '%s\n' "$final_prompt"
367
+ exit 0
368
+ fi
369
+
370
+ printf '%s\n' "$final_prompt" | "${args[@]}"
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env bash
2
+ # codex-run.sh — thin, controllable raw adapter around `codex exec`.
3
+ #
4
+ # Purpose: let a caller (e.g. Claude driving Codex CLI) control, per invocation,
5
+ # the three levers that otherwise silently vary by consumer — raw Codex CLI and
6
+ # codex-plugin-cc inherit the real ~/.codex (AGENTS.md + full config.toml), while
7
+ # ultracode-for-codex subagents run hermetic (no AGENTS.md, minimal config). This
8
+ # raw adapter makes that choice explicit instead of implicit. It is not a policy
9
+ # boundary; callers that pass -c are making expert overrides:
10
+ # (1) AGENTS.md / global instructions — via CODEX_HOME (the --profile)
11
+ # (2) config.toml — via --profile + Codex config profile + -c overrides
12
+ # (3) per-task prompt + output schema — via stdin + --schema
13
+ #
14
+ # Profiles (instruction/config reach):
15
+ # inherit (default) real CODEX_HOME → global + project AGENTS.md + full config.toml
16
+ # hermetic fresh temp CODEX_HOME (auth copied only) + --ignore-user-config,
17
+ # cwd defaults to an empty temp workspace → NO AGENTS.md, NO user
18
+ # config: an independent, uncontaminated lens
19
+ # custom --home DIR CODEX_HOME=DIR → exactly the AGENTS.md/config you place in DIR
20
+ #
21
+ # The prompt is read from stdin. `codex exec` writes the final message to stdout
22
+ # (with --schema, JSON conforming to the schema) and progress to stderr directly.
23
+ # Exit status mirrors `codex exec`.
24
+ #
25
+ # Verified against codex-cli 0.144.1.
26
+ set -euo pipefail
27
+
28
+ usage() {
29
+ cat <<'USAGE'
30
+ Usage: codex-run.sh [--profile inherit|hermetic|custom] [--home DIR]
31
+ [--model M] [--effort E] [--sandbox MODE] [--cd DIR]
32
+ [--bypass-sandbox]
33
+ [--multi-agent auto|on|off]
34
+ [--schema FILE] [--codex-profile NAME] [-p NAME]
35
+ [-c key=value ...] [-] < prompt
36
+ --profile instruction/config reach (default: inherit)
37
+ inherit real CODEX_HOME -> global+project AGENTS.md + full config.toml
38
+ hermetic temp CODEX_HOME -> NO AGENTS.md, NO user config (auth only)
39
+ custom CODEX_HOME=--home -> exactly what you place in that dir
40
+ --home DIR CODEX_HOME for --profile custom (required for custom)
41
+ --model M -m: model to use
42
+ --effort E reasoning effort (none|low|medium|high|xhigh|max|ultra); provider-enforced
43
+ --sandbox read-only (default) | workspace-write | danger-full-access
44
+ --bypass-sandbox
45
+ pass --dangerously-bypass-approvals-and-sandbox instead of --sandbox
46
+ --multi-agent
47
+ auto: on only at Ultra; on/off: explicit native multi-agent state
48
+ --cd DIR working root (-C): decides which project AGENTS.md is seen
49
+ --schema F --output-schema: force the final message to this JSON Schema
50
+ -p NAME
51
+ --codex-profile NAME
52
+ Codex config profile: layer $CODEX_HOME/<name>.config.toml
53
+ -c k=v expert pass-through config override (repeatable); may override
54
+ wrapper defaults, e.g. -c model_verbosity="low"
55
+ - optional explicit stdin marker
56
+ USAGE
57
+ }
58
+
59
+ profile=inherit
60
+ home=""
61
+ model=""
62
+ effort=""
63
+ sandbox="read-only"
64
+ bypass_sandbox=0
65
+ multi_agent=""
66
+ cd_dir=""
67
+ schema=""
68
+ codex_profile=""
69
+ extra_c=()
70
+
71
+ while [ $# -gt 0 ]; do
72
+ case "$1" in
73
+ --profile) profile="${2:?--profile needs a value}"; shift 2 ;;
74
+ --home) home="${2:?--home needs a value}"; shift 2 ;;
75
+ --model) model="${2:?--model needs a value}"; shift 2 ;;
76
+ --effort) effort="${2:?--effort needs a value}"; shift 2 ;;
77
+ --sandbox) sandbox="${2:?--sandbox needs a value}"; shift 2 ;;
78
+ --bypass-sandbox|--dangerously-bypass-approvals-and-sandbox) bypass_sandbox=1; shift ;;
79
+ --multi-agent) multi_agent="${2:?--multi-agent needs auto|on|off}"; shift 2 ;;
80
+ --cd) cd_dir="${2:?--cd needs a value}"; shift 2 ;;
81
+ --schema) schema="${2:?--schema needs a value}"; shift 2 ;;
82
+ --codex-profile|-p) codex_profile="${2:?--codex-profile needs a value}"; shift 2 ;;
83
+ -c) extra_c+=("${2:?-c needs a value}"); shift 2 ;;
84
+ -) shift ;;
85
+ -h|--help) usage; exit 0 ;;
86
+ *) echo "codex-run: unknown argument: $1" >&2; usage >&2; exit 2 ;;
87
+ esac
88
+ done
89
+
90
+ case "$profile" in
91
+ inherit|hermetic|custom) ;;
92
+ *) echo "codex-run: --profile must be inherit|hermetic|custom" >&2; exit 2 ;;
93
+ esac
94
+ case "$multi_agent" in
95
+ ""|auto|on|off) ;;
96
+ *) echo "codex-run: --multi-agent must be auto|on|off" >&2; exit 2 ;;
97
+ esac
98
+
99
+ config_key_from_override() {
100
+ kv="$1"
101
+ case "$kv" in
102
+ *=*) key="${kv%%=*}" ;;
103
+ *) echo "codex-run: -c must be key=value: $kv" >&2; exit 2 ;;
104
+ esac
105
+ case "$key" in
106
+ ''|*[!A-Za-z0-9_.-]*) echo "codex-run: invalid -c key: $key" >&2; exit 2 ;;
107
+ esac
108
+ printf '%s\n' "$key"
109
+ }
110
+
111
+ if [ "${#extra_c[@]}" -gt 0 ]; then
112
+ for kv in "${extra_c[@]}"; do
113
+ config_key_from_override "$kv" >/dev/null
114
+ done
115
+ fi
116
+
117
+ real_home="${CODEX_HOME:-$HOME/.codex}"
118
+ run_home="$real_home"
119
+ cleanup_paths=()
120
+ cleanup_all() {
121
+ if [ "${#cleanup_paths[@]}" -gt 0 ]; then
122
+ for p in "${cleanup_paths[@]}"; do rm -rf "$p"; done
123
+ fi
124
+ }
125
+ trap cleanup_all EXIT
126
+
127
+ if [ "$profile" = "hermetic" ]; then
128
+ root="$(mktemp -d "${TMPDIR:-/tmp}/codex-run-XXXXXX")"
129
+ cleanup_paths+=("$root")
130
+ run_home="$root/home"
131
+ mkdir -p "$run_home"
132
+ # Auth still resolves from CODEX_HOME even with --ignore-user-config, so carry
133
+ # only auth.json across; leave AGENTS.md and config.toml behind.
134
+ cp "$real_home/auth.json" "$run_home/auth.json" 2>/dev/null || true
135
+ # Default cwd to an empty workspace so no project AGENTS.md is picked up.
136
+ if [ -z "$cd_dir" ]; then
137
+ cd_dir="$root/workspace"
138
+ mkdir -p "$cd_dir"
139
+ fi
140
+ elif [ "$profile" = "custom" ]; then
141
+ if [ -z "$home" ]; then echo "codex-run: --profile custom requires --home DIR" >&2; exit 2; fi
142
+ if [ ! -d "$home" ]; then echo "codex-run: --home not a directory: $home" >&2; exit 2; fi
143
+ run_home="$home"
144
+ fi
145
+
146
+ args=(exec --skip-git-repo-check)
147
+ if [ "$bypass_sandbox" -eq 1 ]; then
148
+ args+=(--dangerously-bypass-approvals-and-sandbox)
149
+ else
150
+ args+=(--sandbox "$sandbox")
151
+ fi
152
+ if [ "$profile" = "hermetic" ]; then args+=(--ignore-user-config --ephemeral); fi
153
+ if [ -n "$model" ]; then args+=(--model "$model"); fi
154
+ if [ -n "$cd_dir" ]; then args+=(--cd "$cd_dir"); fi
155
+ if [ -n "$schema" ]; then args+=(--output-schema "$schema"); fi
156
+ if [ -n "$codex_profile" ]; then args+=(--profile "$codex_profile"); fi
157
+ if [ -n "$effort" ]; then args+=(-c "model_reasoning_effort=\"$effort\""); fi
158
+ if [ -n "$multi_agent" ]; then
159
+ if [ "$multi_agent" = "auto" ]; then
160
+ [ "$effort" = "ultra" ] && multi_agent_value=true || multi_agent_value=false
161
+ else
162
+ [ "$multi_agent" = "on" ] && multi_agent_value=true || multi_agent_value=false
163
+ fi
164
+ args+=(-c "features.multi_agent=$multi_agent_value")
165
+ fi
166
+ if [ "${#extra_c[@]}" -gt 0 ]; then
167
+ for kv in "${extra_c[@]}"; do args+=(-c "$kv"); done
168
+ fi
169
+
170
+ # stdin, stdout, and stderr already match this adapter's channel contract.
171
+ set +e
172
+ CODEX_HOME="$run_home" codex "${args[@]}"
173
+ status=$?
174
+ set -e
175
+
176
+ exit "$status"