---
title: "Guardrail rule files"
description: "Write policy as code for tools, paths, branches, spend, egress and deploys, and see how layers combine."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.overlane.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Guardrail rule files

Guardrails are rules in versioned JSON files. Keep the file in your repository, review changes by pull request, and publish what was reviewed. Any agent or person with write access can publish a version. Every published version is an audit event with its author and digest.

```sh
overlane guard rules put --file rules.json --reason "freeze deploys on Fridays"
overlane guard rules list
```

## A rule file

```json rules-file
{
  "version": "1",
  "rules": [
    {
      "id": "team.protect-infra",
      "description": "Nobody pushes infrastructure changes directly",
      "effect": "deny",
      "match": { "tools": ["git.push"], "paths": ["infra/**"] },
      "code": "path_protected",
      "nextCommand": "overlane guard approvals list"
    },
    {
      "id": "team.spend-cap",
      "description": "Stop paid work at 50 dollars a month",
      "effect": "deny",
      "match": { "usage": { "metric": "usd", "atLeast": 50 } },
      "code": "spend_cap_reached",
      "message": "the monthly spend cap of 50 dollars is reached"
    },
    {
      "id": "team.egress",
      "description": "CI may not reach unknown hosts",
      "effect": "deny",
      "match": { "tools": ["egress.fetch"], "hosts": ["*.untrusted.example"] },
      "code": "egress_blocked"
    },
    {
      "id": "team.prod-deploy",
      "description": "Production deploys need an approval",
      "effect": "require_approval",
      "match": { "tools": ["deploy.run"], "environments": ["production"] }
    }
  ]
}
```

## What a rule can match

Every field that is present must match; the values inside one field are alternatives. Globs use `*` within a segment and `**` across segments.

| Field | Matches |
|---|---|
| `principals` | `agent:*`, `user:*` or an ID |
| `roles` | owner, admin, member, viewer, agent |
| `tools` | The action: `git.push`, `git.merge`, `deploy.run`, `egress.fetch`, `api.write`, `review.run` |
| `paths`, `branches`, `repositories`, `environments`, `hosts` | Globs |
| `time` | UTC days and hours |
| `usage` | A measured metric (`usd`, `tokens`, `reviews`) at or above a value, read from the server's own meters |
| `taskHeld` | Whether the caller has an active task |

The effect is `allow`, `deny` or `require_approval`. Plan limits are ordinary rules with a `usage` match.

## How layers combine

There are three layers: **platform** (built in), **team** and **project**. Inside a layer the first matching rule wins, so a layer can carve an exception into its own rules. Across layers the result is the **intersection**: the most restrictive answer stands, and a lower layer can never weaken a higher one. A project rule that allows a push the platform denies changes nothing.

The platform layer protects `main`, `master`, `production` and `release/**` from agents, protects credential files and CI workflows from agents, refuses force-pushes to protected branches, requires approval for production deploys and release promotion, and requires an active task for agent pushes.

## Test a file before you publish it

```sh
overlane guard rules test --file rules.json --tool git.push --path infra/main.tf
overlane guard rules test --file rules.json --tool ci.run --usage usd=50
```

The command evaluates the file locally as the team layer and exits 6 when it would refuse the action.

## What a refusal looks like

A refusal carries a stable code, the rule ID and the exact next command or approval path, and exits with code 6.

```sh
overlane guard check --tool git.push --branch main --task held
```

Source: https://docs.overlane.app/review/guardrail-rules/index.mdx
