---
title: "Guardrails: Kotharo"
version: v0.8.3
canonical: https://kotharo.com/docs/guardrails/
---

# Guardrails

Guardrails watch the shell commands Claude runs and stop the risky ones before they run. They work in every session while Kotharo is on, with or without the team, and whatever the [autonomy level](https://kotharo.com/docs/autonomy-levels/).

A guardrail does one of two things:

- **Hold:** the command waits while Kotharo shows you what it would do, and runs only if you choose **Proceed**.
- **Refuse:** the command never runs, and Claude is told why.

## What the core holds

| Command | Why |
|---|---|
| `git reset --hard` | Throws away uncommitted work |
| `git clean` | Deletes untracked files |
| `git push --force`, `-f`, `--force-with-lease` or a `+` refspec | Overwrites the remote branch |
| `dotnet ef database update` against a named or non-local database | Changes a shared database's schema |

Before it asks, Kotharo measures what the command would do, such as the files `git clean` would delete or the commits a force-push would drop, and shows that with the command.

The core refuses nothing outright. A team profile can add commands to hold or refuse, below.

## How a hold works

A hold opens a pane, or draws in the band where there is no pane:

```text
╭──────────────────────────────────────────────────────────────╮
│ ⚠ Guardrails · git reset --hard                              │
│ Command  git reset --hard                                    │
│ Would    discard uncommitted changes in 3 files              │
│                                                              │
│   src/export.ts                                              │
│   src/export.test.ts                                         │
│   README.md                                                  │
│                                                              │
│ 1 Proceed  2 Cancel  Claude is waiting on your answer        │
╰──────────────────────────────────────────────────────────────╯
```

- **Cancel** is the default, so pressing Enter by mistake runs nothing.
- **Proceed** runs the command as it was.
- A hold you don't answer in 10 minutes is cancelled. So is one that hits an error.

When a hold is cancelled, Claude is told the command didn't run, what it would have done, and not to retry it unless you ask. One hold shows at a time.

With [teaching mode](https://kotharo.com/docs/teaching-mode/#guardrail-lessons) on, a hold or a refusal also says why the command is risky and what to do instead.

## Add your team's own

A [team profile](https://kotharo.com/docs/team-profile/#guardrails) can turn on more kinds in its own `hooks/guardrail-rules.mjs`:

| Field | What it does |
|---|---|
| `name` | The name shown on holds and refusals |
| `destructiveGit` | Hold the git commands above |
| `efDatabaseUpdate` | Hold `dotnet ef database update` against a database that isn't local |
| `sqlcmd` | Hold `sqlcmd` against a server that isn't local, unless the SQL can't write |
| `denyStacks` | Refuse `cdk deploy`, `cdk destroy` and CloudFormation changes to the stacks listed, each with a reason |
| `cloudflareAccounts` | Hold `wrangler deploy` to the Cloudflare accounts listed |
| `loggedInCloudflareAccount` | The account `wrangler` falls back to, which must be one of those listed |

A profile also holds `cdk` commands with `--all`. Every kind is off unless the file turns it on. Turn each kind on in one plugin only, so a command is never held twice.

## What guardrails are not

Guardrails catch commands. They sit beside the team's other safety rules, not in place of them: the actions that [always ask](https://kotharo.com/docs/autonomy-levels/#what-always-asks), and the rules every session loads, such as never committing secrets and never pushing to `main` without your OK.

Next: [Worklogs and continuity](https://kotharo.com/docs/worklogs-and-continuity/). [All docs](https://kotharo.com/docs/)

Written for Kotharo v0.8.3.
