The CLI is published on npm (npm i -g @aex-lang/cli). APIs are experimental and may change before v1.0. Roadmap →
Skip to content

Codex CLI

AEX provides two ways to enforce contracts with OpenAI Codex CLI:

  1. MCP Proxy (recommended) — aex proxy sits between Codex and upstream MCP servers, gating every tool call against your policy
  2. Static validationaex check validates contracts before a Codex run

Important: AEX only guards tool calls routed through aex proxy. If Codex calls tools directly (e.g., shell commands via its built-in sandbox), those calls bypass AEX. Use aex proxy for MCP-based tool servers where you need enforcement.

aex proxy vs aex run

CommandPurposeWhen to use
aex proxyMCP proxy — gates every tool call in real timeOngoing agent sessions, exploratory work under policy
aex runExecute a specific task contract end-to-endOne-shot contract execution with full audit trail

aex proxy is a long-running process that sits between the client and server. aex run parses a contract, runs each step sequentially, and exits. Use aex proxy for policy enforcement during interactive sessions; use aex run when you have a specific contract to execute.

MCP Proxy Setup

1. Create a policy

bash
aex init --policy

This scaffolds .aex/policy.aex:

aex
policy workspace v0

goal "Default security boundary for this repository."

allow file.read, file.write, tests.run, git.*
deny network.*, secrets.read

confirm before file.write

budget calls=100

2. Preview effective permissions

bash
aex effective

To see how a task contract narrows the policy:

bash
aex effective --contract tasks/fix-bug.aex

3. Run with the proxy

Start the proxy between Codex and your MCP server:

bash
aex proxy --auto-confirm -- npx -y your-mcp-server

The proxy auto-discovers .aex/policy.aex. To also apply a task contract:

bash
aex proxy --contract tasks/fix-bug.aex -- npx -y your-mcp-server

What the proxy does

  • Filters tools/list — removes tools not in the allow list or in the deny list
  • Gates tools/call — blocks denied tools, unapproved tools, and budget-exceeded calls
  • Enforces confirmation — blocks tools requiring confirmation (pass --auto-confirm to bypass)
  • Emits audit logs — every decision is logged as structured JSON to stderr

Static Validation

Validate contracts before running:

bash
# Validate contract syntax and semantics
aex check tasks/fix-bug.aex

# Validate policy file
aex check .aex/policy.aex

CI Integration

Validate contracts on every push to catch permission drift:

yaml
- name: Validate AEX contracts
  run: |
    npx @aex-lang/cli check tasks/*.aex
    npx @aex-lang/cli check .aex/policy.aex
    npx @aex-lang/cli fmt tasks/*.aex --check

Merge Semantics

When a policy and task contract are both active, effective permissions are the most restrictive combination:

  • Allow = policy allow ∩ task use (intersection)
  • Deny = policy deny ∪ task deny (union)
  • Confirm = policy confirm ∪ task confirm (union)
  • Budget = min(policy budget, task budget)

Audit Trail

The proxy emits structured JSON to stderr for every decision. Each event includes timestamps for correlation:

bash
aex proxy 2>audit.json -- npx -y your-mcp-server

For aex run, pass --log-json or --otlp-endpoint for structured logs with OpenTelemetry-compatible trace IDs.

Contract Mode

For tasks that modify code, use the draft → review → run workflow:

bash
# Generate a contract from a prompt
aex draft "fix the failing test in src/foo.ts" --model openai

# Review it
aex review .aex/runs/20260502-fix-test.aex

# Approve and execute
aex review .aex/runs/20260502-fix-test.aex --run --model openai

Or ask Codex to write the contract directly, then validate and run:

bash
aex check .aex/runs/fix-test.aex
aex review .aex/runs/fix-test.aex --run

The runtime enforces tool permissions, checks, confirmations, and budgets. The model generates artifacts inside bounded make steps — it cannot directly write files or call tools outside the contract.

Session Checkpoints

The proxy's meta-tools let Codex checkpoint and resume sessions across conversations.

Save Progress

Mid-session, Codex can save the current state:

Codex: calls aex.checkpoint({ name: "fix-auth", description: "Identified the bug" })

This writes the audit log, budget state, and tool call history to .aex/checkpoints/fix-auth/.

Resume Later

In a new session, Codex can resume:

Codex: calls aex.resume({ name: "fix-auth" })

The proxy restores the budget counter and returns the session context (what tools were called, what was accomplished) so Codex can continue without repeating work.

Discover Contracts

Codex can list available task contracts and checkpoints:

Codex: calls aex.list_tasks()
Codex: calls aex.review_task({ task: "tasks/fix-test.aex" })

Meta-tools are automatically available when using aex proxy. See the Meta-Tools Reference for full details.

Troubleshooting

Proxy not intercepting calls

Make sure the upstream command comes after --:

bash
# Correct
aex proxy -- npx -y your-mcp-server

# Wrong — proxy tries to parse npx as a flag
aex proxy npx -y your-mcp-server

Policy not found

The proxy auto-discovers .aex/policy.aex in the working directory. If your policy is elsewhere:

bash
aex proxy --policy path/to/policy.aex -- npx -y your-mcp-server

Tools missing from Codex

The proxy filters tools/list responses, removing tools that are denied or not allowed. If a tool disappears, check your policy's allow and deny lists:

bash
aex effective

Budget resets

Budget is tracked per proxy session. Restarting the proxy resets the counter. Use checkpoints to persist budget state across sessions.

See Also

Prompts are not permissions. Plans are not contracts.