state-hub/scripts/configure-codex.sh
tegwick 5927591be8
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Multi-Context Image / build-and-push (push) Successful in 1m0s
Prepare State Hub retirement baseline
2026-08-09 16:19:53 +02:00

142 lines
4.9 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
CODEX_HOME_DIR="${CODEX_HOME:-$HOME/.codex}"
CONFIG_PATH="${CODEX_CONFIG_PATH:-$CODEX_HOME_DIR/config.toml}"
API_BASE="${API_BASE:-http://127.0.0.1:8000}"
DRY_RUN=0
SKIP_VERIFY=0
MCP_MODE="remove"
MCP_NAME="${STATE_HUB_MCP_NAME:-dev-hub}"
MCP_COMMAND="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/codex-state-hub-mcp.sh"
usage() {
cat <<'USAGE'
Usage: scripts/configure-codex.sh [options]
Enable direct network access for Codex workspace-write sandboxes and verify
that the sandbox can reach the local State Hub.
Options:
--codex-home DIR Codex home containing config.toml. Default: $CODEX_HOME or ~/.codex.
--api-base URL State Hub API base. Default: http://127.0.0.1:8000.
--dry-run Show the configuration change without writing it.
--skip-verify Do not run the sandboxed State Hub health check.
--with-mcp Opt in to the experimental slim State Hub MCP server.
--skip-mcp Do not add or remove a State Hub MCP registration.
-h, --help Show this help.
USAGE
}
while [ "$#" -gt 0 ]; do
case "$1" in
--codex-home)
test -n "${2:-}" || { echo "ERROR: --codex-home requires a directory" >&2; exit 2; }
CODEX_HOME_DIR="$2"
CONFIG_PATH="$CODEX_HOME_DIR/config.toml"
shift 2
;;
--api-base)
test -n "${2:-}" || { echo "ERROR: --api-base requires a URL" >&2; exit 2; }
API_BASE="$2"
shift 2
;;
--dry-run) DRY_RUN=1; shift ;;
--skip-verify) SKIP_VERIFY=1; shift ;;
--with-mcp) MCP_MODE="add"; shift ;;
--skip-mcp) MCP_MODE="skip"; shift ;;
-h|--help) usage; exit 0 ;;
*) echo "ERROR: unknown argument: $1" >&2; usage >&2; exit 2 ;;
esac
done
python3 - "$CONFIG_PATH" "$DRY_RUN" <<'PY'
import re
import sys
import tomllib
from pathlib import Path
path = Path(sys.argv[1])
dry_run = sys.argv[2] == "1"
original = path.read_text(encoding="utf-8") if path.exists() else ""
if original:
tomllib.loads(original)
header = "[sandbox_workspace_write]"
lines = original.splitlines()
start = next((i for i, line in enumerate(lines) if line.strip() == header), None)
if start is None:
if lines and lines[-1].strip():
lines.append("")
lines.extend([header, "network_access = true"])
else:
end = next(
(i for i in range(start + 1, len(lines)) if re.match(r"^\s*\[", lines[i])),
len(lines),
)
setting = next(
(i for i in range(start + 1, end) if re.match(r"^\s*network_access\s*=", lines[i])),
None,
)
if setting is None:
lines.insert(end, "network_access = true")
else:
lines[setting] = "network_access = true"
updated = "\n".join(lines).rstrip() + "\n"
tomllib.loads(updated)
if updated == original:
print(f"OK: {path} already enables sandbox workspace-write network access")
elif dry_run:
print(f"DRY-RUN: would enable sandbox_workspace_write.network_access in {path}")
else:
path.parent.mkdir(parents=True, exist_ok=True)
temporary = path.with_suffix(path.suffix + ".tmp")
temporary.write_text(updated, encoding="utf-8")
temporary.chmod(0o600)
temporary.replace(path)
print(f"OK: enabled sandbox_workspace_write.network_access in {path}")
PY
if [ "$MCP_MODE" = "add" ]; then
if [ "$DRY_RUN" -eq 1 ]; then
echo "DRY-RUN: would register Codex MCP server $MCP_NAME -> $MCP_COMMAND"
elif ! command -v codex >/dev/null 2>&1; then
echo "WARN: codex is not on PATH; State Hub MCP registration was skipped." >&2
elif CODEX_HOME="$CODEX_HOME_DIR" codex mcp get "$MCP_NAME" >/dev/null 2>&1; then
echo "OK: Codex MCP server $MCP_NAME is already registered"
else
CODEX_HOME="$CODEX_HOME_DIR" codex mcp add "$MCP_NAME" -- "$MCP_COMMAND"
echo "OK: registered Codex MCP server $MCP_NAME -> $MCP_COMMAND"
fi
elif [ "$MCP_MODE" = "remove" ]; then
if [ "$DRY_RUN" -eq 1 ]; then
echo "DRY-RUN: would remove Codex MCP server $MCP_NAME if registered"
elif command -v codex >/dev/null 2>&1 \
&& CODEX_HOME="$CODEX_HOME_DIR" codex mcp get "$MCP_NAME" >/dev/null 2>&1; then
CODEX_HOME="$CODEX_HOME_DIR" codex mcp remove "$MCP_NAME"
echo "OK: removed Codex MCP server $MCP_NAME; use REST/statehub CLI by default"
else
echo "OK: Codex MCP server $MCP_NAME is not registered"
fi
fi
if [ "$DRY_RUN" -eq 1 ] || [ "$SKIP_VERIFY" -eq 1 ]; then
exit 0
fi
if ! command -v codex >/dev/null 2>&1; then
echo "WARN: codex is not on PATH; configuration was written but not verified." >&2
exit 0
fi
HEALTH_URL="${API_BASE%/}/state/health"
if timeout 10 codex sandbox -- curl -fsS --max-time 3 "$HEALTH_URL" >/dev/null 2>&1; then
echo "OK: Codex sandbox can reach State Hub at $HEALTH_URL"
else
echo "WARN: Codex sandbox still cannot reach $HEALTH_URL." >&2
echo "WARN: A managed permission profile may enforce restricted networking/--unshare-net." >&2
echo "WARN: Retry State Hub REST/CLI commands with escalated execution or change the managed profile." >&2
fi