Package Exports
- @controlzero/core
Readme
controlzero
AI agent governance for Node.js. Policies, audit, and observability for tool calls. Works locally with no signup.
Hello World
import { Client } from '@controlzero/core';
const cz = new Client({
policy: {
rules: [
{ deny: 'delete_*', reason: 'Hello World: deletes are blocked' },
{ allow: '*', reason: 'Hello World: everything else is fine' },
],
},
});
console.log(cz.guard('delete_file', { args: { path: '/tmp/foo' } }).decision); // "deny"
console.log(cz.guard('read_file', { args: { path: '/tmp/foo' } }).decision); // "allow"12 lines. No API key. No signup. Run it.
Install
npm install @controlzero/core
# or
pnpm add @controlzero/core
# or
yarn add @controlzero/coreWhy
Your AI agents call tools. Some of those tools should never be called by an
agent without a human in the loop. controlzero is the policy layer between
the model's output and the tool execution. Decisions are fail-closed by default.
You can use it offline with a local YAML file or JS object. When you want to
share policies across a team or get a hosted audit dashboard, sign up at
controlzero.ai and set CONTROLZERO_API_KEY.
Quickstart with the CLI
# Use npx if you do not want a global install
npx -y @controlzero/core init
# Or after installing globally:
npm install -g @controlzero/core
controlzero init
controlzero validate
controlzero test delete_fileThe generated controlzero.yaml is the tutorial. It ships with annotated
rules covering allow lists, deny lists, wildcards, and the catch-all.
Templates available:
controlzero init— Hello World template (default)controlzero init -t rag— RAG agent template (block exfiltration)controlzero init -t mcp— MCP server templatecontrolzero init -t cost-cap— model allow-listing and cost guards
Loading a policy
Three ways:
import { Client } from '@controlzero/core';
// From a JavaScript object
const cz1 = new Client({
policy: {
rules: [{ deny: 'delete_*' }, { allow: 'read_*' }],
},
});
// From a YAML file
const cz2 = new Client({ policyFile: './controlzero.yaml' });
// From an environment variable
// (set CONTROLZERO_POLICY_FILE=./controlzero.yaml)
const cz3 = new Client();If ./controlzero.yaml exists in the current directory, it is picked up
automatically. No env var needed.
Policy schema
version: '1'
rules:
- deny: 'delete_*'
reason: 'Deletes need human approval'
- allow: 'search'
- allow: 'read_*'
- allow: 'github:list_*'
- deny: 'github:delete_repo'
- deny: '*'
reason: 'Default deny'Rules are evaluated top to bottom. The first match wins. If no rule matches, the call is denied (fail-closed).
Local audit log
When running without an API key, every decision is written to ./controlzero.log
with daily rotation. Configure via the client:
const cz = new Client({
policyFile: './controlzero.yaml',
logPath: './logs/controlzero.log',
logRotation: '10 MB',
logRetention: '30 days',
logFormat: 'json', // or 'pretty'
});When CONTROLZERO_API_KEY is set, audit ships to the remote dashboard and
these log* options are ignored with a warning.
Hybrid mode
If you set both an API key AND pass a local policy, the local policy overrides the dashboard policy and you get a loud WARN log on init:
WARNING: controlzero: manual policy override detected. ...For prod environments, opt into strict mode to throw instead:
const cz = new Client({
apiKey: 'cz_live_...',
policy: localPolicy,
strictHosted: true,
});
// throws HybridModeErrorHosted mode
Hosted mode (dashboard policies + remote audit) is not yet implemented in this slim package. To use hosted mode today, install the legacy package:
npm install @controlzero/sdkFor local-first use cases, this controlzero package is what you want.
Coding agent hooks (one command)
Install controlzero as a pre-tool-use hook in your AI coding CLI. Every tool
call gets evaluated against your policy before it runs. Audit log lives at
~/.controlzero/audit.log.
# Claude Code
npx -y @controlzero/core install claude-code
# Gemini CLI
npx -y @controlzero/core install gemini
# Codex CLI (Bash-only coverage today; pair with Gateway for full enforcement)
npx -y @controlzero/core install codexAll three write the same global policy at ~/.controlzero/policy.yaml and
patch the agent's settings file in place. Run again to update; idempotent.
| Agent | Settings file | Hook event | Coverage |
|---|---|---|---|
| Claude Code | ~/.claude/settings.json |
PreToolUse |
All tool calls |
| Gemini CLI | ~/.gemini/settings.json |
BeforeTool |
All tool calls |
| Codex CLI | ~/.codex/hooks.json + config.toml |
PreToolUse |
Bash only (apply_patch + MCP bypass) |
The Codex coverage gap is upstream (OpenAI's hook system is gated behind a feature flag and only fires for Bash today). Use the Control Zero Gateway as the authoritative gate for non-Bash actions.
Framework examples
Full integration guides at docs.controlzero.ai/sdk/integrations:
- LangChain.js
- LangGraph.js
- OpenAI Agents SDK
- Anthropic tool use
- Vercel AI SDK
- MCP servers
- Raw HTTP / no framework
License
Apache 2.0