@contro1/claude-code
v0.2.2
Published
Contro1 human-approval hook for selected Claude Code actions
Maintainers
Readme
Contro1 for Claude Code
Route selected Claude Code actions to the right human and resume only after Contro1 returns an approved decision. Use it for production deploys, sensitive file changes, infrastructure mutations, database operations, privileged MCP tools, or any other action your organization requires a manager to approve.
The quickstart uses a production deploy because it is easy to understand and
demo safely. That is the default policy, not the limit of the connector. Set
CENTCOM_GATE_MODE=all and select tool names with CENTCOM_TOOLS to gate every
matching tool call before execution. Normal reads and unrelated tools keep moving.
Five-minute production deploy demo
- Install the CLI and connector, then register this coding-agent identity:
curl -fsSL https://raw.githubusercontent.com/contro1-hq/contro1-cli/main/install.sh | sh
npm install -g @contro1/claude-code
contro1 auth login --mode agent
contro1 init --name "Claude Code - developer laptop"
contro1 auth print-access-token --yesThe last command prints the live agent token once. Copy it into your user-level Claude settings, then clear the terminal. Never put it in the repository:
{
"env": {
"CENTCOM_API_KEY": "cc_live_xxx",
"CENTCOM_BASE_URL": "https://api.contro1.com/api/centcom/v1",
"CENTCOM_GATE_MODE": "deploy",
"CENTCOM_REQUIRED_ROLE": "cto",
"CENTCOM_ENVIRONMENT": "production",
"CENTCOM_TARGET": "billing-api",
"CENTCOM_FALLBACK": "deny",
"CENTCOM_TIMEOUT": "900000"
}
}- Add the project hook in
.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "centcom-claude-code",
"timeout": 910,
"statusMessage": "Waiting for production deploy approval"
}
]
}
]
}
}Copyable files are in examples/convenience and
examples/CLAUDE.md.
- Ask Claude Code:
Deploy billing-api to production with npm run deploy:production.Claude Code reaches the matching PreToolUse hook. The connector sends the redacted
command, command hash, repository commit, workspace-state hash, target, risk,
and policy trigger to Contro1. The CTO can approve or reject in the Dashboard,
Slack, or Teams. Timeout, API failure, or rejection returns deny.
What the reviewer sees
The request uses the public canonical request shape:
context.action: the proposed tool and redacted input structure;context.machine_observed: command hash, commit, workspace state, target, environment, hook event, and permission mode;context.agent_reported: optional agent justification, clearly separated from trusted facts;policy_trigger: why the action requires human authorization;routing.required_role: who is eligible to approve;approval_policy: quorum, roles, separation of duties, and fail-closed timeout.
The connector never lets agent-written text choose the reviewer, risk level, or approval policy.
Gate actions beyond deploy
The connector can gate any selected Claude Code tool action at the PreToolUse
boundary. For example, require manager approval for every
write, edit, shell command, or privileged MCP tool:
{
"env": {
"CENTCOM_GATE_MODE": "all",
"CENTCOM_TOOLS": "Bash,Write,Edit,mcp__production_database__execute",
"CENTCOM_REQUIRED_ROLE": "engineering-manager",
"CENTCOM_POLICY_REASON": "Selected sensitive Claude Code actions require manager approval"
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash|Write|Edit|mcp__production_database__execute",
"hooks": [
{
"type": "command",
"command": "centcom-claude-code",
"timeout": 910
}
]
}
]
}
}This gates matching tool calls before execution, not the model's private
reasoning or every internal step. PreToolUse is recommended because it runs
regardless of whether Claude Code would otherwise show a permission dialog and
also works in non-interactive flows. Existing PermissionRequest configurations
remain supported, but only run when Claude Code is about to prompt the user.
Prefer narrow tool and command policies to avoid approval fatigue.
Ask a human for input
Approval and human input are separate interactions. A selected action creates an
approval request and must end in Approve or Reject. A decision comment explains
that outcome; it does not replace the proposed tool input.
When Claude needs information, use the companion CLI to create a free_text
request. The operator's canonical decision is respond, and the returned string
can be used by Claude as the next workflow input:
contro1 ask "Which production region should I use?" \
--role platform-owner \
--wait \
--format jsonIn the default deploy mode this control-plane command is not gated because it
is not a deploy. In all mode every selected Bash call is gated, including
contro1 ask; use a separate input path until the connector includes a dedicated
AskUserQuestion relay. Do not add a Respond button to an approval request: it
would leave the proposed action without a terminal Approve or Reject decision.
Convenience setup versus enforced setup
Convenience gate
The project hook above is the fastest developer setup. It protects against an autonomous or accidental sensitive Claude Code action while preserving normal workflow.
It is not an organization security boundary:
- a developer can edit or remove a project hook;
PreToolUseprotects only actions executed through that configured Claude Code client;- a developer with direct credentials can perform the same action outside Claude Code.
Use this setup for evaluation, personal guardrails, and a polished demo. Set:
"CENTCOM_ENFORCEMENT_SETUP": "convenience"Enforced enterprise setup
For organization-controlled Claude Code, deliver the hook and its environment through managed settings, disable permission bypass, and prevent unmanaged hooks or permission rules from weakening policy.
Example managed settings (adjust command rules to your deployment stack):
{
"allowManagedHooksOnly": true,
"allowManagedPermissionRulesOnly": true,
"forceRemoteSettingsRefresh": true,
"permissions": {
"disableBypassPermissionsMode": "disable"
},
"env": {
"CENTCOM_GATE_MODE": "deploy",
"CENTCOM_REQUIRED_ROLE": "cto",
"CENTCOM_ENVIRONMENT": "production",
"CENTCOM_ENFORCEMENT_SETUP": "enterprise",
"CENTCOM_FALLBACK": "deny"
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/opt/contro1/bin/centcom-claude-code",
"timeout": 910,
"statusMessage": "Waiting for Contro1 approval"
}
]
}
]
}
}Start from
examples/enterprise/managed-settings.json,
then deliver it through your organization's supported managed-settings channel.
Provide CENTCOM_API_KEY through a managed secret or environment channel; the
example intentionally does not contain a credential.
Managed settings make the Claude Code path non-bypassable from user or project configuration. They still do not stop a human from opening another terminal. For that guarantee, remove standing production credentials from developer machines and let a CI/deployment broker obtain credentials only after the Contro1 approval job succeeds. See the CI template in the public CLI repo.
Do not add a matching managed ask rule unless you intentionally want a second
local confirmation after Contro1 approval. PreToolUse already runs before the
tool call; explicit Claude Code deny rules remain useful for actions that must
never run under any approval.
Configuration
| Variable | Default | Purpose |
|---|---|---|
| CENTCOM_API_KEY | required | Agent-scoped Contro1 token |
| CENTCOM_BASE_URL | hosted API | Contro1 API base URL |
| CENTCOM_GATE_MODE | deploy | deploy gates recognized deploy commands; all gates every configured tool |
| CENTCOM_TOOLS | Bash | Comma-separated Claude tools considered by the connector |
| CENTCOM_DEPLOY_MATCH | built-ins | Additional regular expression for an organization-specific deploy command |
| CENTCOM_REQUIRED_ROLE | cto | Eligible reviewer role |
| CENTCOM_REQUIRED_APPROVALS | 1 | Approval quorum, up to 20 |
| CENTCOM_ENVIRONMENT | production | Environment shown to the reviewer |
| CENTCOM_TARGET | empty | Service, cluster, account, or deployment target |
| CENTCOM_POLICY_REASON | production approval policy | Trusted policy trigger |
| CENTCOM_AGENT_JUSTIFICATION | empty | Optional agent-reported explanation; never used for routing |
| CENTCOM_ENFORCEMENT_SETUP | convenience | Evidence label: convenience or enterprise |
| CENTCOM_FALLBACK | deny | Failure behavior; keep deny for production |
| CENTCOM_TIMEOUT | 900000 | Wait timeout in milliseconds |
| CENTCOM_POLL_INTERVAL | 3000 | Poll interval in milliseconds |
| CENTCOM_SLA_MINUTES | 10 | Reviewer SLA before escalation |
| CENTCOM_CORRELATION_ID | session id | Groups related requests into one case |
You can place the same keys in .centcom.json, but secrets belong in user or
managed settings, not a committed project file.
Built-in deploy recognition
The default policy recognizes common deployment mutations from npm/pnpm/yarn, Make, Kubernetes, Helm, Terraform/OpenTofu, Pulumi, Vercel, Netlify, AWS, Google Cloud, Azure, and GitHub workflow dispatch. Add your internal wrapper:
{
"env": {
"CENTCOM_DEPLOY_MATCH": "(^|\\s)ship-prod(\\s|$)"
}
}Prefer explicit command patterns. Gating every Bash call creates approval
fatigue and trains reviewers to rubber-stamp.
Decision comments
The API key's decision_comment_policy controls the reviewer experience:
optional: approve or reject in one click;risk_based: comments are required for rejection and high/critical decisions;always: every approval decision requires a comment.
The request can tighten this policy but cannot weaken the API-key policy.
Security properties and limits
- The connector fails closed by default and cancels timed-out requests.
- Secret-looking values are redacted before context is sent to a reviewer.
- The hash is computed from the original command/input before redaction.
- Quorum uses distinct reviewers when separation of duties is enabled.
- Contro1 records the human decision; local execution evidence remains client-reported unless the deployment system provides its own attestation.
- A managed hook protects the Claude Code execution path. A credential boundary at CI or the deployment service protects the production system itself.
Development
npm install
npm run build
npm packRelated repositories:
- contro1-cli — CLI, Codex adapter, and CI template
- centcom-sdk — TypeScript SDK
- centcom-claude-managed-agents — server-side managed-agent bridge
