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

# Policy Management

> Create, list, and manage Unbound policy types from the CLI

Unbound has three policy types: **Cost**, **Security**, and **Tool**. Each has its own subcommand for type-specific creation. Generic commands (list, get, delete) work across Cost and Security; Tool policies use a separate `policy tool` subcommand.

Listing and inspecting policies (`list`, `get`, `form-data`, and the `policy tool` list, get, families and mcp-servers commands) needs **Admin or Analytics Viewer**. Creating, updating and deleting policies, including `--prompt` AI assist, needs **Admin**; an Analytics Viewer gets `Admin access required`.

## Reference data

Before creating policies, pull the available user groups, models, guardrails, and tool types:

```bash theme={null}
unbound policy form-data
```

## Generic commands (Cost / Security)

```bash theme={null}
unbound policy list                    # List all policies
unbound policy list --type COST        # Filter by type: COST, SECURITY
unbound policy list --enabled          # Only show currently enabled policies
unbound policy list --search "budget"  # Filter by name substring
unbound policy get <id>                # View a policy's full config
unbound policy delete <id>             # Delete a policy (prompts to confirm)
unbound policy delete <id> --yes       # Delete without the confirmation prompt
unbound policy effective <id>          # Effective policies for a user (default)
unbound policy effective <id> --user   # Same, stated explicitly
unbound policy effective <id> --group  # Treat <id> as a user-group ID instead
```

<Note>
  Use the type-specific commands — `policy cost create`, `policy security create`, and the `policy tool` family below — for guided, flag-based create and update. Each also has an `update <id>` that changes only the fields you pass.
</Note>

Each type has its own `list` too, with columns tuned to that type. The cost and security lists take `--json` and nothing else; `policy tool list` also filters and pages, as shown below. The `--enabled` filter lives only on `policy list`:

```bash theme={null}
unbound policy cost list
unbound policy security list
unbound policy cost update <id> --monthly-budget 2000
```

***

## Cost policies

Set a monthly spend limit per user group:

```bash theme={null}
unbound policy cost create \
  --name "Engineering Budget" \
  --monthly-budget 1000 \
  --group engg
```

| Flag | Description |
| - | - |
| `--group <names\|ids>` | Comma-separated user groups to scope the policy to. Omit to apply org-wide |
| `--priority <n>` | Lower numbers take precedence. Auto-assigned if omitted |
| `--disabled` | Create the policy without turning it on — useful for staging a change before you enable it |

```bash theme={null}
unbound policy cost create \
  --name "Platform team budget" \
  --monthly-budget 5000 \
  --group platform \
  --priority 10 \
  --disabled
```

The same three flags work on `policy security create`, with one difference in how they resolve: **every matching security policy applies, and the strictest action wins for each guardrail.** For cost policies, one policy wins outright — the one with the lowest priority number.

See [Cost Policies](/policies/cost-policies) for all configuration options.

***

***

## Security policies

Apply guardrails for PII and secrets detection:

```bash theme={null}
# Block requests containing PII:
unbound policy security create \
  --name "Block PII" \
  --sub-type guardrails \
  --guardrail PII:BLOCK

# Audit requests containing secrets:
unbound policy security create \
  --name "Audit Secrets" \
  --sub-type guardrails \
  --guardrail SECRETS:AUDIT
```

`--guardrail` takes `<name>:<action>[:<threshold>]` and is repeatable. The guardrails are `PII` and `Secrets`; each supports the actions `BLOCK` and `AUDIT`. `unbound policy form-data` lists them with their allowed actions. The optional third part is the threshold — the guardrail acts only once that many instances are found in one request. It defaults to `1`, and the CLI accepts `1` to `100`:

```bash theme={null}
unbound policy security create \
  --name "Block bulk PII" \
  --sub-type guardrails \
  --guardrail PII:BLOCK:5
```

Run `unbound policy form-data` for the guardrail names available to you.

See [Security Policies](/policies/security-policies) for all configuration options.

***

## Tool policies

Tool policies control shell commands and MCP tool calls. They have their own command group, `unbound policy tool`, rather than sharing the generic `policy` commands — `unbound policy list`, `get` and `delete` cover Cost and Security only, and each one's `--help` says so.

### List and inspect

```bash theme={null}
unbound policy tool list
unbound policy tool list --type TERMINAL   # or MCP
unbound policy tool list --search "rm"     # match name, description, or command family
unbound policy tool get <id>
unbound policy tool delete <id>            # prompts to confirm; add --yes to skip
```

Tool policies are paginated at 50 per page:

| Flag | Description |
| - | - |
| `--page <n>` | Page number (default 1) |
| `--page-size <n>` | Results per page (default 50) |
| `--all` | Fetch every page (may be slow for large orgs) |

### Discover available targets

```bash theme={null}
unbound policy tool families      # Terminal command families and the fields they accept
unbound policy tool mcp-servers   # Known MCP servers and their available tools
```

### Create a terminal command policy

```bash theme={null}
unbound policy tool create-terminal --no-ai \
  --name "Block deletions under /etc" \
  --command-family delete_file \
  --field path='/etc/*' \
  --action BLOCK \
  --custom-message "Destructive command blocked by policy."
```

`--command-family` takes a **family** name, and `--field` takes a field that family accepts. Families are grouped into categories — `filesystem`, `cloud`, `database`, `network` and the rest — and a category is not a family: `--command-family filesystem` comes back *Unknown command family: filesystem*. The families under `filesystem` are `read_file`, `write_file` and `delete_file`, which is why the example above targets `delete_file`. Run `unbound policy tool families` for the families your organization can target and the fields each one accepts, or see [Command family reference](/policies/tool-policies#command-family-reference).

To match the whole raw command line instead of a field, use the `custom` family, below.

#### Describe it in plain English

If you don't know the family or the field to match on, describe what you want and let Unbound author the policy:

```bash theme={null}
unbound policy tool create-terminal --prompt "block rm -rf"
```

You get a preview of the policy it drafted and a confirmation step before anything is created. Each `--prompt` run creates **exactly one policy**, so describe one rule at a time. Add `--yes` to skip the confirmation (the preview still prints), or `--no-ai` to use the raw classification flags instead.

`--prompt` can't be combined with `--command-family`, `--field`, or `--config`. You can still pass `--name`, `--description`, `--action`, `--custom-message`, `--group`, `--disabled`, `--yes` and `--json`.

<Note>
  `create-terminal` and `create-mcp` need you to pick a mode: either `--prompt "<description>"` for AI assist, or `--no-ai` to pass the raw classification flags. Running either with neither exits `2`.

  `--no-ai` is refused when the CLI detects it is running inside Claude Code, to steer agents toward AI assist. Set `UNBOUND_ALLOW_NO_AI_UNDER_CLAUDE=1` if you're driving the terminal yourself.

  Whenever the resolved action is `BLOCK` or `WARN`, `--custom-message` is required — those policies always need a user-facing message.
</Note>

Tool policies can't scope by environment, project, time window, or exception clause. If your prompt mentions one — "production", "after hours", "except…" — the CLI warns that those parts will be ignored and asks whether to continue. Prompts are capped at 1,800 characters.

#### Match a command we don't classify

Most commands fall into a family (`delete_file`, `cloud_destroy`, `git_action`, …). When yours doesn't, or you want to match one exact command rather than a category, use the **`custom`** family and give it the whole command pattern:

```bash theme={null}
unbound policy tool create-terminal --no-ai \
  --name "Block the release script" \
  --command-family custom \
  --field command='make release-prod' \
  --action BLOCK \
  --custom-message "Use the release pipeline instead."
```

`custom` takes a single `command` field — the pattern is matched against the whole command line, and it is the only key a custom policy may carry. Run `unbound policy tool families` to see every family and the fields each one accepts.

A `custom` pattern that reads as a regex cannot use lookahead (`(?=`, `(?!`), lookbehind (`(?<=`, `(?<!`), atomic groups (`(?>`) or backreferences (`\1`–`\9`, `\k<name>`) — those are refused at create time with *Invalid pattern: …*. Rewrite without them, or use an exact or `*`-wildcard pattern, which are matched literally and not checked this way. Ordinary field patterns have no such restriction.

### Create an MCP tool policy

```bash theme={null}
# Match by action type (e.g. all write operations on a server):
unbound policy tool create-mcp --no-ai \
  --name "Audit Linear writes" \
  --mcp-server Linear \
  --mcp-action-type write \
  --action AUDIT

# Match a specific tool:
unbound policy tool create-mcp --no-ai \
  --name "Block PR creation" \
  --mcp-server GitHub \
  --mcp-tool create_pull_request \
  --action BLOCK \
  --custom-message "Open pull requests through the normal review flow."
```

Available actions: `BLOCK`, `WARN`, `AUDIT`, `REQUIRE_SLACK_APPROVAL`

### Update a tool policy

Only the fields you pass are changed:

```bash theme={null}
unbound policy tool update <id> --action WARN
```

| Flag | Applies to | Description |
| - | - | - |
| `--name <name>` | both | New policy name |
| `--description <text>` | both | New description |
| `--action <action>` | both | `BLOCK`, `WARN`, `AUDIT`, or `REQUIRE_SLACK_APPROVAL` |
| `--custom-message <text>` | both | Message shown when the policy fires (required for `BLOCK` / `WARN`) |
| `--group <names\|ids>` | both | Replace the user-group scope |
| `--enabled` / `--disabled` | both | Turn the policy on or off |
| `--command-family <family>` | terminal | New command family |
| `--field <key=pattern>` | terminal | Replace match fields; repeatable (ANDed) |
| `--mcp-server <server>` | mcp | New MCP server |
| `--mcp-tool <tool>` | mcp | New MCP tool (mutually exclusive with `--mcp-action-type`) |
| `--mcp-action-type <type>` | mcp | New action type: `read`, `write`, `destructive` |

The cost and security policy types each have an `update <id>` too. `policy cost update` takes `--monthly-budget` plus `--name`, `--group`, `--priority` and `--enabled` / `--disabled`. `policy security update` takes those shared flags, but guardrail and routing changes go through `--config '<json>'` — the create-time `--sub-type` / `--guardrail` / `--route` flags aren't accepted on update:

```bash theme={null}
unbound policy cost update <id> --monthly-budget 2000
unbound policy security update <id> --disabled
```

***

See [Tool Policies](/policies/tool-policies) for the full list of actions, NL rules, and canonical group targeting.

Every list, get, create and update command supports `--json` for machine-readable output. `delete` doesn't — it takes only `--yes`.

<CardGroup cols={2}>
  <Card title="Tool Policies" icon="shield" href="/policies/tool-policies">
    Dashboard reference for actions, NL rules, and Slack approvals
  </Card>

  <Card title="Cost Policies" icon="dollar-sign" href="/policies/cost-policies">
    Dashboard reference for budget limits and spend controls
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.