---
title: "Govern Claude Code"
---

# Govern Claude Code

Enforce agent policy in Claude Code with managed settings, route its model traffic through the Neural Inverse Govern gateway, and use the Claude Code session controls.

## Control level

| What | Level |
|---|---|
| Agent actions (shell, files, web fetch, MCP tools) | **Enforced** on devices where Govern's managed settings are installed |
| Model traffic | **Network**: holds while Claude Code sends requests to the gateway |
| Hooks a developer adds in their own user settings | Advisory |

Claude Code reads a managed settings file from an operating system location that users cannot override. Govern compiles the agent policy into that file, and the endpoint agent installs it.

## 1. Write the policy

Write rules in **Agent policy**; see [Agent policy](https://neuralinverse.com/docs/govern/agent-policy/).

## 2. Enrol the machine

Install and enrol the endpoint agent (`keystone-agent`) on the developer's machine; see [Deploy](https://neuralinverse.com/docs/deploy/). The agent fetches the policy compiled for the `claude-code` engine, verifies its signature and installs `managed-settings.json` at:

| OS | Path |
|---|---|
| Linux | `/etc/claude-code/managed-settings.json` |
| macOS | `/Library/Application Support/ClaudeCode/managed-settings.json` |
| Windows | `C:\Program Files\ClaudeCode\managed-settings.json` |

The agent owns this file and removes it when it is uninstalled.

## 3. What the managed settings contain

- `permissions.allow`, `permissions.ask` and `permissions.deny` from the rules Claude Code can express, with `defaultMode: "default"`.
- `disableBypassPermissionsMode: "disable"` and `disableAutoMode: "disable"`, so an ask reaches a person, not a classifier.
- `allowManagedPermissionRulesOnly: true` and `allowManagedHooksOnly: true`, so user and project settings cannot add allow rules or hooks.
- A `PreToolUse` hook with matcher `*` that runs `keystone-agent policy enforce --engine claude-code`, which enforces the rules Claude Code cannot express itself, and one entry per organisation-approved hook.

| Policy kind | Compiled to | Gaps the endpoint agent enforces |
|---|---|---|
| `shell` | `Bash(<pattern>)` | None |
| `file_read` | `Read(<path>)` | Programs that open files without naming them; reported as gaps while shell commands may run |
| `file_write` | `Edit(<path>)` | As `file_read` |
| `network` | `WebFetch(domain:<host>)` | Egress from shell commands |
| `mcp_tool` | `mcp__server__tool` | Allow globs other than after a literal server |
| `git_push`, `git_force_push`, `package_install`, `model` | Not expressible | All; model choice is also enforced by the gateway |
| Ask with named approvers | `ask` | The named approval |

A revoked policy denies every tool by name and `*`.

## 4. Check the preview

Open **Agent policy > Policy preview**, choose the person, the project and the engine `claude-code`, and read the gaps. Gaps are enforced only where the endpoint agent runs.

## 5. Route model traffic through the gateway

Open **Models > Connect a coding tool** for the values of your deployment. The settings, for `~/.claude/settings.json` or the managed settings file:

```json
{
  "apiKeyHelper": "keystone-cli token models --tool claude_code",
  "env": {
    "ANTHROPIC_BASE_URL": "<your API URL>/api/v1/models/gateway",
    "CLAUDE_CODE_API_KEY_HELPER_TTL_MS": "900000"
  }
}
```

1. Install the `keystone-cli` your administrator provides and put it on `PATH`.
2. Give it a credential: set `KEYSTONE_URL` and either enrol the machine with the endpoint agent or export `KEYSTONE_TOKEN`.
3. Check it: `keystone-cli token models --tool claude_code` prints a token starting with `nigw_`.
4. Write the settings above, or deploy them as managed settings with your device management tool.
5. Start Claude Code. Its requests appear in **Models > Request logs** under the person's name.

Claude Code runs the credential command itself and refreshes the short-lived token every 15 minutes and on any `401`. Deployed as managed settings, the base URL and credential helper cannot be changed in Claude Code, but other clients and keys can still reach Anthropic unless your network blocks them.

## Claude Code session controls

The **AI tool controls** service (marked beta in the console) has Claude Code pages: Claude Code (sessions), Claude Code policy, Claude Code managed settings, and Claude Code pauses and stops. Sessions can be killed, paused and resumed (`/api/v1/claude/sessions/{id}/kill`, `/pause`, `/resume`), and tool policies and MCP allow and deny rules (`/api/v1/claude/tool-policies`, `/api/v1/claude/mcp-rules`) are managed there. Changes need `controls:manage`; reading sessions needs `security:read`.

The Claude Code managed settings page generates a separate `managed-settings.json` from these tool policies and MCP rules, for devices without the endpoint agent. Its hooks send each tool call to the endpoint agent, or, without the agent, to Govern with the person's own key in `KEYSTONE_HOOK_TOKEN`; a tool call neither decides is refused. Tool policies only narrow what agent policy allows: agent policy is authoritative.

## Audit

Claude Code can push OpenTelemetry events to Govern's vendor audit receiver; see [Evidence](https://neuralinverse.com/docs/evidence/). Policy decisions are in **Agent decisions**, and hook decisions in **AI tool decisions**.
