Quickstart
Run your first AEX contract in under five minutes.
Install
npm install -g @aex-lang/cliOr run without installing:
npx @aex-lang/cli check tasks/fix-test.aexCreate a Policy
Every repo starts with a policy — the ambient security boundary:
aex init --policyThis creates .aex/policy.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=100Edit it to match your repo's needs. Policies define what tools are available, which are denied, and which require human approval.
Draft a Contract from a Prompt
The fastest way to create a task contract:
aex draft "fix the failing test in src/foo.ts" --model anthropicThis generates a validated contract in .aex/runs/. Review it:
aex review .aex/runs/20260502-fix-failing-test.aexApprove and execute:
aex review .aex/runs/20260502-fix-failing-test.aex --runThe model drafts. You review. AEX executes with full enforcement.
Write a Contract by Hand
For reusable workflows, write contracts directly. Create tasks/fix-test.aex:
task fix_test v0
goal "Fix the failing test with the smallest safe change."
use file.read, file.write, tests.run
deny network.*, secrets.read
need test_cmd: str
need target_files: list[file]
do tests.run(cmd=test_cmd) -> failure
do file.read(paths=target_files) -> sources
make patch: diff from failure, sources with:
- fix the failing test
- preserve public behavior
- do not touch unrelated files
check patch is valid diff
check patch touches only target_files
confirm before file.write
do file.write(diff=patch) -> result
do tests.run(cmd=test_cmd) -> final
check final.passed
return finalValidate It
aex check tasks/fix-test.aexScaffold Files
aex init --task fix-testThis generates a starter contract plus matching inputs and policy files under tasks/.
Preview Effective Permissions
See the merged permissions when policy and task are combined:
aex effective --contract tasks/fix-test.aexOutput:
Policy: .aex/policy.aex
Contract: tasks/fix-test.aex
Allowed:
file.read
file.write
tests.run
Denied:
network.*
secrets.read
Confirmation required:
file.write
Budget:
calls=20The allow list is the intersection (only tools both policy and task agree on), deny is the union (everything either blocks), and budget is the minimum.
Compile to JSON IR
aex compile tasks/fix-test.aexThe JSON output captures permissions, needs, and step sequence for downstream runtimes. The CLI validates the result against the official IR schema before printing.
Format the Contract
aex fmt tasks/fix-test.aexAdd --check to ensure formatting during CI without rewriting files:
aex fmt tasks/fix-test.aex --checkRun It
aex run tasks/fix-test.aex \
--inputs examples/fix-test/inputs.json \
--policy examples/fix-test/policy.json \
--auto-confirmThe runtime enforces contract permissions and policy budgets. Without --auto-confirm, the CLI blocks at confirm before file.write and reports that confirmation is required.
Audit Log
The runtime logs every tool call and check to stdout:
{"event":"run.started","agent":"fix_test","version":"v0"}
{"event":"tool.allowed","tool":"tests.run","step":1}
{"event":"tool.result","tool":"tests.run","bind":"failure"}
{"event":"tool.allowed","tool":"file.read","step":2}
{"event":"tool.result","tool":"file.read","bind":"sources"}
{"event":"make.result","bind":"patch","type":"diff"}
{"event":"check.passed","condition":"patch is valid diff"}
{"event":"check.passed","condition":"patch touches only target_files"}
{"event":"confirm.required","tool":"file.write"}
{"event":"confirm.approved","tool":"file.write"}
{"event":"tool.allowed","tool":"file.write","step":3}
{"event":"tool.result","tool":"file.write","bind":"result"}
{"event":"tool.allowed","tool":"tests.run","step":4}
{"event":"tool.result","tool":"tests.run","bind":"final"}
{"event":"check.passed","condition":"final.passed"}
{"event":"run.finished","status":"success"}Enforce with Claude Code
Built-in tools (aex gate)
Add to .claude/settings.json:
{
"hooks": {
"PreToolUse": [{ "matcher": ".*", "command": "aex gate" }]
}
}aex gate maps Claude Code tools (Write, Bash, etc.) to AEX capabilities (file.write, shell.exec) and gates them against your policy.
MCP tools (aex proxy)
aex proxy --auto-confirm -- npx -y your-mcp-serverThe proxy auto-discovers .aex/policy.aex. See the Claude Code and Codex integration guides for full setup.
How make Works
make steps ask a model to generate an artifact (like a diff or a draft). When you run aex run, the runtime delegates make to a model handler.
Default behavior: Without a model handler, aex run blocks at the first make step and reports that no model handler is configured.
Using OpenAI:
export AEX_MODEL=openai
export OPENAI_API_KEY=sk-...
aex run tasks/fix-test.aex --inputs examples/fix-test/inputs.json --policy examples/fix-test/policy.jsonUsing a custom handler:
aex run tasks/fix-test.aex --model-handler ./my-handler.tsA model handler is a function that receives the make step description (type, inputs, instructions) and returns the generated artifact. See the OpenAI Agents integration for a full example.
Sign and Verify the Contract
Attach provenance metadata before shipping a contract:
aex sign tasks/fix-test.aex --id maintainer --key-file ./signing.keyVerify the metadata later:
aex verify tasks/fix-test.aex \
--signature tasks/fix-test.aex.signature.json \
--key-file ./signing.keyThe signature file records the hash, signer, and timestamp, giving security teams an audit trail for every contract revision.