Control plane
Discover and onboard local agents with itr, apply policy YAML, and approve privileged tools, without mixing runtime keys into dashboard APIs.
Two planes
Production data plane is the Intertrace Gateway on Fly at https://intertrace.fly.dev. Clients send LLM / MCP / A2A traffic with itr_rt_*. The kernel remains POST https://intertrace.fly.dev/v1/actions/authorize.
The control plane is the dashboard at platform.intertrace.ai: inventory, policy authoring, approvals, imported spend, and Agent Control. It is not a second authorize engine. YAML you apply compiles into the same authorize intents the gateway already enforces.
Two keys
Mint an org API key in Settings → API keys. New keys start itr_; older bst_ keys keep working. Send it as X-Intertrace-Key (or Authorization: Bearer itr_…). Runtime itr_rt_* keys stay on Fly and are rejected on control-plane routes.
itr CLI
itr is Intertrace’s control-plane CLI. itr login signs the machine in through the browser (no key to paste) and mints this device's runtime key for each coding tool. itr connect installs the hooks and itr doctor says PROTECTED only after an allowed and a denied action went through as expected. Discover is local (no key). Onboard rewrites MCP / base_url to Fly, writes a .intertrace.bak next to the config, then posts inventory to Estate. Offboard restores the backup.
curl -fsSL https://platform.intertrace.ai/install.sh | sh # or: npm install -g intertrace
itr login # browser approval; or INTERTRACE_API_KEY=itr_… (org key, never itr_rt_*)
itr connect all # claude-code | cursor | codex | copilot | opencode | all
itr doctor
itr discover
itr onboard --runtime cursor --gateway https://intertrace.fly.dev
itr policy apply --file policy.yaml
itr approvals list
itr usage import --file cursor.csv
itr permission-hook --source claude_code # stdin event, stdout native JSONPermission hook: pipe the host event to itr permission-hook --source claude_code (or cursor / codex_cli / copilot_cli / opencode). itr connect installs the hook for you, plus a prompt hook that keeps your latest request on this machine so the intent check can read it. Prompt hooks never hold a prompt.
Dashboard surfaces
Discovery
Cloud, code, identity and local-agent inventory
Work → Approvals
One inbox. Timeout fail-closed. Approve is not execute.
Work → CI flows
CI and evidence-pack templates
Policies → Policy as code
Validate, diff, apply YAML (ours or a Preloop v1.0 document)
Costs → Imported
Cursor/Claude/Codex spend sidecar, never a Fly 402
Settings
Runtime keys vs org API keys
Agent Control (OpenClaw / Hermes) queues an audited user turn on an existing agent, never a hidden system prompt. Connect clients: Cursor, Claude Desktop, Devin, Codex.
Permission hooks
Native Claude Code, Cursor, Codex, Copilot CLI, and OpenCode hooks ask the enforcer: itr permission-hook calls POST /v1/actions/authorize on the gateway with the device’s runtime key for that tool, the one itr login mints. When a person must approve, the hook waits for the decision in Work → Approvals and tells you it is waiting; a timeout or an undecided approval is a deny with the approval's link, on every host. The editor's own prompt never stands in for a central approval. A block is never downgraded. Without a device runtime key for the tool, the hook allows only workspace reads.
Confirm in the editor. When every reason for an ask is developer-level (a new tool during the learning period, download and run, a privileged command you can judge) and the call is outside production, the enforcer can hand the question to you at the keyboard instead of opening a central approval. This works in interactive Claude Code and for Cursor shell and MCP calls, and an organization admin can turn it off. Anything leaving the company still goes to the inbox.
Codex runs a hook only after you trust it in /hooks; itr doctor reports an untrusted or disabled Codex hook as not protected. The old /api/runtime/permission-check route is retired and answers 426 ITR_UPGRADE_REQUIRED; update itr if you see it.