Provider-agnostic policy runtime

Make your coding agents obey the rules.

One .policyctl.yml, enforced inside Claude Code, Codex, and Cursor at tool-call time — and again as a hard gate in CI. Not prompt text. Not a vendor denylist.

$ npm i -g @policyctl/cli Read the docs →
Free · MIT · local-first Optional hosted control plane
policyctl check
$ policyctl check --from main ✓ PASS no-secrets-in-commits no secret patterns detected ⚠ WARN tests-for-source src/auth.ts changed without a test ✗ FAIL migrations-via-generator db/migrations/0004.sql lacks generator signature 2 blocking · 1 warning — build stopped
Built for
Staff engineers running mixed-agent stacks. Claude Code · Codex · Cursor · CI pipelines.
12
CLI commands
3
agent providers
8
rule matchers
custom rules
The gap

Prompt files don't enforce anything.

Claude ignores half of an over-specified CLAUDE.md. Agents treat workflow rules as suggestions. Teams waste weeks hand-rolling per-model plugins that still let migrations through without a generator signature. There is no shared, deterministic policy layer across Claude Code, Codex, and Cursor — until now.

PROMPT FILES

Soft. Ignored.

CLAUDE.md, .cursorrules, AGENTS.md

Advisory only. Claude truncates over-long instructions. No exit code. No CI gate. No audit trail.

VENDOR DENYLISTS

Locked-in. Shallow.

Claude permissions · Codex exec policy

Hard within one provider. Useless in a mixed-agent stack. Each vendor's API is different — you rebuild the same rules 3×.

How it works

Three commands. One file. No backend required.

The CLI is local-first and offline. The hosted control plane (optional) adds cross-repo policy versioning and an audit trail.

01 · INIT

Scaffold

Start from a template that encodes procedural rules, not opinions.

policyctl init --template full
02 · WIRE

Generate hooks

Write the exact glue for each provider — no hand-rolled per-model plugin.

policyctl gen claude policyctl gen codex policyctl gen cursor
03 · CHECK

Gate the diff

Fail CI on violations and stream them to the dashboard feed.

policyctl check policyctl check --report
Provider-agnostic

One policy file. Every coding agent. Every repo.

Write a rule once in .policyctl.yml and it enforces identically inside Claude Code's PreToolUse hooks, Codex's exec-policy, Cursor's hooks.json, and your GitHub Actions CI.

Claude Code

PreToolUse hooks

Hooks fire on every tool call. Exit-2 blocks the call before it happens.

Codex

Exec-policy + sandbox

Starlark rules gate commands before execution. Policyctl generates the rules file.

Cursor

hooks.json

Command hooks on preToolUse. One config for the whole team.

CI / GitHub Actions

policyctl check

Fail the build on any blocking rule. Same engine, same YAML, same verdict.

Audit trail

Optional cloud

Stream violations to the hosted dashboard. Local CLI works fully offline.

The sharpest edge

Hard guardrails vs. soft prompts.

Prompt files and vendor denylists are advisory. policyctl exits with a real error code that blocks the tool call and fails CI. Here's the difference:

Prompt files
CLAUDE.md / .cursorrules
Vendor denylists
Claude permissions / Codex exec
policyctl
This file + hooks + CI
Cross-agent Partial Locked-in Yes
Deterministic (not advisory) No Yes Yes
CI integration No No Yes
Audit trail No No Yes
Exit code on violation No One vendor Every agent + CI
Procedural rules No No Yes
What you can enforce

Encode the rules prompts can't.

A rule is a matcher set + an enforce level + a scope. Compose them, allowlist reviewed exceptions, and tag them. Hook-time and CI-time share the same engine.

Migrations via generator

block · both

Block any migration file that lacks the generator signature — at hook time and in CI.

No protected edits

block · hook

Prevent agents from touching README, package.json, or any path you choose.

No secrets in commits

fail · ci

Regex-detect AWS keys, GitHub tokens, and OpenAI keys in the diff, then fail the build.

Tests for source

warn · ci

Warn when a src/ change ships without a matching test file.

policyctl is the only thing that stopped our agent from rewriting migrations by hand. Now we have one rule file across Claude Code, Codex, and Cursor — and CI fails if any agent tries to cheat.

A Staff Engineer
at a Series-A dev-tooling company
Pricing

Free CLI. Paid control plane. No surprises.

The local CLI is free, open-source, and fully featured. The hosted control plane adds policy versioning, audit logs, and a live dashboard — only when you need it.

Local
CLI
$0

Complete local-first experience. Hooks, CI gate, and procedural rules. MIT licensed.

  • One .policyctl.yml
  • Claude Code, Codex, Cursor hooks
  • CI gate
  • Audit dashboard
Install now
Enterprise
Self-hosted
Custom

Run the control plane behind your firewall. Includes support and custom integrations.

  • Everything in Cloud
  • Self-hosted (Cloudflare Workers)
  • SSO / SAML
  • Dedicated support
Contact sales
FAQ

Questions we get asked.

Is policyctl free?

The CLI is free and open-source (MIT). The hosted control plane is $5/month with a 14-day free trial. No credit card required for local use.

Does it work with my CI provider?

Yes. policyctl check is a single binary that exits non-zero on violations. Works with GitHub Actions, GitLab CI, CircleCI, Bazel, and any shell-based CI.

Can I enforce rules specific to one agent?

Yes. Use the match.agents field in your YAML to scope rules per provider (claude, codex, cursor) or to ci.

Is my source code sent to the cloud?

No. The CLI runs entirely locally. The optional control plane only receives violation metadata (file paths, rule IDs, agent) — never source code or secrets.

Open source

Stop shipping agent accidents.

One file, every agent, every repo. The CLI is free forever.