# How Continue Enforces Rules and Policies for Code Modification

> Learn how Continue enforces rules and policies for code modification. Discover its three-layer architecture for secure and controlled code changes in your repository.

- Repository: [Continue/continue](https://github.com/continuedev/continue)
- Tags: how-to-guide
- Published: 2026-06-24

---

**Continue treats every code-modification request as a policy-governed operation using a three-layer architecture—declarative YAML configuration, runtime API retrieval, and client-side evaluation—that applies the most restrictive rule available to determine whether tools are blocked, require user approval, or execute automatically.**

Continue, an open-source AI code assistant in the `continuedev/continue` repository, implements a **policy engine** that governs file edits, refactoring operations, and terminal commands. Rather than executing AI-generated changes blindly, the system evaluates each request against organization-wide and local rules stored in [`continue.yaml`](https://github.com/continuedev/continue/blob/main/continue.yaml), ensuring developers maintain explicit control over automated modifications.

## The Three-Layer Policy Architecture

Continue's policy system operates across distinct layers that transform static configuration into runtime enforcement decisions.

### Policy Definition via YAML Schema

The foundation lives in [`packages/config-yaml/src/schemas/policy.ts`](https://github.com/continuedev/continue/blob/main/packages/config-yaml/src/schemas/policy.ts), which defines a Zod schema for the `Policy` type. Developers declare rules in [`.continue/policy.yaml`](https://github.com/continuedev/continue/blob/main/.continue/policy.yaml) or embedded within [`continue.yml`](https://github.com/continuedev/continue/blob/main/continue.yml), specifying whether individual tools are `disabled`, `allowedWithPermission`, or `allowedWithoutPermission`.

```yaml

# .continue/policy.yaml

tools:
  # Block all write operations

  write: disabled
  # Allow read-only tools automatically

  read: allowedWithoutPermission
  # Require approval for test runners

  testRunner:
    permission: allowedWithPermission

```

### Runtime Policy Retrieval

When the IDE extension or CLI initializes, it fetches the effective organizational policy from the Continue backend. The TypeScript SDK wrapper in [`packages/continue-sdk/typescript/api/src/apis/DefaultApi.ts`](https://github.com/continuedev/continue/blob/main/packages/continue-sdk/typescript/api/src/apis/DefaultApi.ts) exposes this via the `GET /ide/policy` endpoint:

```typescript
import { DefaultApi } from "continue-sdk/typescript/api";

async function loadEffectivePolicy() {
  const api = new DefaultApi();
  const response = await api.getIdePolicy();
  return response.data?.policy; // Merges with local config
}

```

### Client-Side Policy Evaluation

The core evaluator resides in [`gui/src/redux/thunks/evaluateToolPolicies.ts`](https://github.com/continuedev/continue/blob/main/gui/src/redux/thunks/evaluateToolPolicies.ts). This module merges the base policy from local YAML with any dynamic server-provided overrides, applying a **most-restrictive-wins** algorithm. For terminal commands specifically, [`packages/terminal-security/src/evaluateTerminalCommandSecurity.ts`](https://github.com/continuedev/continue/blob/main/packages/terminal-security/src/evaluateTerminalCommandSecurity.ts) performs additional token-level analysis to calculate the final policy state.

## Evaluating Tool Calls Against Policies

Before executing any tool, Continue calls `evaluateToolPolicies(toolName, args)` to determine the permission state. The function returns one of three enum values defined in [`gui/src/util/toolCallState.ts`](https://github.com/continuedev/continue/blob/main/gui/src/util/toolCallState.ts):

- **`disabled`**: The tool is blocked and Continue displays an error explaining the security risk.
- **`allowedWithPermission`**: The UI renders an approval button; execution pauses until the user clicks it.
- **`allowedWithoutPermission`**: The tool runs immediately without interruption.

```typescript
import { evaluateToolPolicies } from "./evaluateToolPolicies";

async function runTool(toolName: string, args: any) {
  const { policy } = await evaluateToolPolicies(toolName, args);
  
  if (policy === "disabled") {
    showError(`Tool "${toolName}" is disabled by policy`);
    return;
  }
  
  if (policy === "allowedWithPermission") {
    const approved = await askUserApproval(toolName);
    if (!approved) return;
  }
  
  // Execute if allowedWithoutPermission or after approval
  await executeTool(toolName, args);
}

```

The UI layer in [`gui/src/redux/thunks/streamNormalInput.ts`](https://github.com/continuedev/continue/blob/main/gui/src/redux/thunks/streamNormalInput.ts) consumes this result to decide whether to auto-execute a stream or present a permission dialog.

## Special Handling for Terminal Commands

Raw terminal commands receive additional scrutiny because they can affect the host system. The `evaluateTerminalCommandSecurity` module in [`packages/terminal-security/src/evaluateTerminalCommandSecurity.ts`](https://github.com/continuedev/continue/blob/main/packages/terminal-security/src/evaluateTerminalCommandSecurity.ts) walks parsed command tokens, calculates the most restrictive policy for each segment, and returns the overall security classification.

Commands classified as `allowedWithoutPermission` proceed to the backend immediately. All others trigger the permission flow or block execution entirely, preventing potentially destructive shell operations from running without explicit consent.

## Updating Policies at Runtime

Continue supports dynamic policy changes without requiring an IDE restart. The CLI offers `continue policy add …` commands that write new rules to the YAML configuration. These changes trigger `ToolPermissionService.reloadPermissions()` in [`extensions/cli/src/services/ToolPermissionService.ts`](https://github.com/continuedev/continue/blob/main/extensions/cli/src/services/ToolPermissionService.ts), which rebuilds the in-memory permission list so subsequent tool calls respect the updated rules instantly.

## Security Guarantees

The policy engine provides three critical safety mechanisms:

- **Least-privilege default**: Unlisted tools default to `disabled`, requiring explicit enablement.
- **No escalation**: Dynamic policies from the server cannot override a `disabled` base rule; the merge logic always selects the most restrictive option.
- **Visibility**: When tools are blocked or require approval, the UI displays clear messages constructed in [`evaluateToolPolicies.ts`](https://github.com/continuedev/continue/blob/main/evaluateToolPolicies.ts) that include the specific policy reason.

## Summary

- Continue governs code-modification requests through a declarative YAML policy system defined in [`packages/config-yaml/src/schemas/policy.ts`](https://github.com/continuedev/continue/blob/main/packages/config-yaml/src/schemas/policy.ts).
- The effective policy merges local configuration with organization-wide rules retrieved via `DefaultApi.getIdePolicy()`, with the most restrictive rule taking precedence.
- The `evaluateToolPolicies` thunk determines whether tools are `disabled`, `allowedWithPermission`, or `allowedWithoutPermission` before execution.
- Terminal commands undergo additional security evaluation via [`evaluateTerminalCommandSecurity.ts`](https://github.com/continuedev/continue/blob/main/evaluateTerminalCommandSecurity.ts) to prevent unauthorized system access.
- The `ToolPermissionService` enables runtime policy updates without restarting the IDE or CLI.

## Frequently Asked Questions

### How do I disable a specific tool in Continue?

Create a [`.continue/policy.yaml`](https://github.com/continuedev/continue/blob/main/.continue/policy.yaml) file in your project root and set the tool to `disabled`. For example, add `write: disabled` under the `tools` key to block all write operations. The configuration is parsed by the Zod schema in [`packages/config-yaml/src/schemas/policy.ts`](https://github.com/continuedev/continue/blob/main/packages/config-yaml/src/schemas/policy.ts) and enforced immediately.

### Can server-side policies override local restrictions?

No. When the client merges the base policy from [`continue.yaml`](https://github.com/continuedev/continue/blob/main/continue.yaml) with dynamic rules from the `GET /ide/policy` endpoint, it selects the most restrictive option available. A `disabled` rule in your local YAML cannot be overridden by an `allowed` rule from the server, ensuring that local security constraints remain authoritative.

### What happens when a tool requires permission?

The UI displays an "Approve?" button generated by the stream handling logic in [`gui/src/redux/thunks/streamNormalInput.ts`](https://github.com/continuedev/continue/blob/main/gui/src/redux/thunks/streamNormalInput.ts). The tool execution pauses until you explicitly click to approve. If you deny the request or the policy evaluation returns `disabled`, Continue shows an error message constructed in [`evaluateToolPolicies.ts`](https://github.com/continuedev/continue/blob/main/evaluateToolPolicies.ts) explaining the block.

### How does Continue secure terminal commands?

Terminal commands are evaluated by `evaluateTerminalCommandSecurity` in [`packages/terminal-security/src/evaluateTerminalCommandSecurity.ts`](https://github.com/continuedev/continue/blob/main/packages/terminal-security/src/evaluateTerminalCommandSecurity.ts), which analyzes command tokens to determine the applicable policy. Unlike standard tools, commands must be explicitly `allowedWithoutPermission` to execute automatically; otherwise, they follow the standard approval flow or are blocked.