Claude Code guardrails policy examples: fintech, open source, agency work

Three starter policies for the agent-guardrails plugin, what each one is for, and how to write one of your own.

A guardrails policy is a small JSON file that says what your agent may not do in this project. The free agent-guardrails plugin ships three starter policies. This guide explains the file format, walks through each starter and the reasoning behind it, then shows how to write your own.

The policy file format

The active policy is .claude/guardrails.json in your project. It is plain JSON with no comments. Install the plugin, then copy a starter into place:

/plugin marketplace add RichFloForge/agent-guardrails
/plugin install agent-guardrails@agent-guardrails-marketplace
/agent-guardrails:init --policy strict-fintech

The init command writes the policy, plus a commented reference file called .claude/guardrails.example.jsonc that the plugin does not read. It will not overwrite an existing policy unless you pass --force.

The top-level keys are fail_closed, protected_branches, rules and audit. Under rules sit four rules: destructive_shell, secrets_in_content, protected_paths and scope_shell. Each has enabled and mode, which is block or warn. In warn mode the call goes ahead, a warning is printed and the decision is logged.

How merging works

Your file is merged over the plugin's default.json. The rule is simple. Objects merge key by key. Lists replace the default list.

This means a tiny file is valid. To switch on the banned-commands rule and keep every other default, this is the whole policy:

{ "rules": { "scope_shell": { "enabled": true } } }

It also means a list is all or nothing. If you write a paths list for protected_paths, it replaces the default list, so keep the two .claude/guardrails entries in it. They stop the agent editing its own policy. The starters all do this.

Two glob notes. A pattern with no / matches any path component, so .env matches app/.env. A pattern with a / is matched against the whole project-relative path, and ** crosses directories.

Starter 1: strict-fintech

This is for teams where a stray edit or command has real consequences: payments, ledgers, regulated data. The idea is to say what the agent may touch, rather than listing what it may not. Key parts:

{
  "fail_closed": true,
  "protected_branches": ["main", "master", "production", "release", "staging", "develop"],
  "rules": {
    "protected_paths": {
      "paths": [".env", ".env.*", "**/*.pem", "**/*.key", "**/*.p12", "**/*.pfx", "**/id_rsa*",
                ".git/**", "**/.git/**", "**/secrets/**", ".claude/guardrails.json",
                ".claude/guardrails.*.json", "**/credentials*", ".github/workflows/**",
                "**/migrations/**", "terraform/**"],
      "scope": { "enabled": true, "allowed_paths": ["src/**", "tests/**", "docs/**", "README.md"] }
    },
    "scope_shell": {
      "enabled": true,
      "mode": "block",
      "blocked_commands": ["npm publish", "pip install", "terraform apply", "terraform destroy",
                           "kubectl delete", "kubectl apply", "docker push", "aws s3 rm",
                           "gh release", "psql", "mysql"]
    }
  }
}

The reasoning:

Note that its secret scan has no test* exemption, so fixtures with realistic-looking keys will be flagged.

Starter 2: oss-maintainer

This is for a maintainer who wants to review everything, but does not want friction while working. It fails open and bans only release commands.

{
  "fail_closed": false,
  "protected_branches": ["main", "master"],
  "rules": {
    "secrets_in_content": { "ignore_paths": ["*.md", "*.example", "test*", "docs/**"] },
    "protected_paths": {
      "paths": [".env", ".env.*", "**/*.pem", "**/*.key", "**/id_rsa*", ".git/**", "**/.git/**",
                "**/secrets/**", ".claude/guardrails.json", ".claude/guardrails.*.json", "LICENSE"]
    },
    "scope_shell": {
      "enabled": true,
      "mode": "block",
      "blocked_commands": ["npm publish", "twine upload", "cargo publish", "gh release create"]
    }
  }
}

The reasoning:

Starter 3: agency-client-work

This is for people working in client repositories they do not own. The risk is touching things that belong to someone else, or pushing to servers by accident. This starter warns rather than blocks for shell commands.

{
  "protected_branches": ["main", "master", "production", "staging"],
  "rules": {
    "protected_paths": {
      "paths": [".env", ".env.*", "**/*.pem", "**/*.key", "**/id_rsa*", ".git/**", "**/.git/**",
                "**/secrets/**", ".claude/guardrails.json", ".claude/guardrails.*.json",
                "**/wp-config.php", "**/vendor/**", "**/node_modules/**"]
    },
    "scope_shell": {
      "enabled": true,
      "mode": "warn",
      "blocked_commands": ["npm publish", "terraform apply", "kubectl delete", "git push",
                           "rsync", "scp", "ssh"]
    }
  }
}

The reasoning:

If you would rather block than warn, change mode to block.

Writing your own

Start from the closest starter and cut it down. Then follow these steps.

  1. Decide what must never happen, and write that down first. Protected branches and protected paths are the most useful.
  2. Choose warn or block for each rule. Warn mode is a good way to see what a rule would catch before you enforce it.
  3. Add scope only if you can list the folders the agent should work in.
  4. Run the agent for a day, then read the audit report and adjust.

A small example that combines several features:

{
  "protected_branches": ["main", "master", "release/*"],
  "rules": {
    "protected_paths": {
      "scope": { "enabled": true, "allowed_paths": ["src/**", "tests/**"] },
      "allow_paths": [".env.example", "src/config/local.json"]
    },
    "scope_shell": {
      "enabled": true,
      "mode": "warn",
      "blocked_commands": ["npm publish", "docker push"]
    },
    "secrets_in_content": {
      "patterns": [
        { "name": "nhs-number", "regex": "\\b\\d{3} \\d{3} \\d{4}\\b", "mode": "warn" }
      ]
    }
  }
}

This protects release/* branches, limits edits to src/ and tests/, bans two commands in warn mode, and adds a custom secret pattern that warns but does not block. The allow_paths entries are exceptions to the protected paths, and also exempt that file from scope. Because paths is not set, the default protected paths still apply.

All three starters are starting points, not compliance guarantees. Review them against your own rules. Policies reduce risk. They do not replace sandboxing, review or backups. Read how destructive command blocking works, including its limits, before you rely on it.

More policies

If you want more starting points, there is an optional Team Pack with 8 more policies for £24. The plugin and the three starters above are free, and they are enough for most projects.

Related guides