https://github.com/harikrishnareddyl/cato
Universal AI agent safety layer — protect files and commands with configurable rules
https://github.com/harikrishnareddyl/cato
ai claude-code cli developer-tools rust safety security
Last synced: about 2 months ago
JSON representation
Universal AI agent safety layer — protect files and commands with configurable rules
- Host: GitHub
- URL: https://github.com/harikrishnareddyl/cato
- Owner: Harikrishnareddyl
- License: mit
- Created: 2026-04-26T03:35:38.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-04-26T07:08:12.000Z (about 2 months ago)
- Last Synced: 2026-04-26T07:25:50.310Z (about 2 months ago)
- Topics: ai, claude-code, cli, developer-tools, rust, safety, security
- Language: Rust
- Size: 191 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Cato
Universal AI agent safety layer. Drop a `.cato.toml` in your project, and it protects your files and commands from any AI coding agent.
```
npm install -g cato-cli # coming soon
pip install cato-cli # coming soon
brew install cato # coming soon
cargo install cato # from source
```
## Quick start
```bash
# In your project
cato init # creates .cato.toml with default rules
cato adapt claude-code # sets up Claude Code hooks
cato check .env # test: denied
cato check main.rs # test: allowed
```
That's it. Any AI agent with hooks configured will now respect your rules.
## How it works
```
AI agent tries to read .env
|
v
Agent hook → cato hook claude-code (reads stdin JSON)
|
v
Walks up from cwd, finds .cato.toml
|
v
Evaluates rules: .env matches "*.env" → deny
|
v
Returns {"permissionDecision": "deny"} → agent blocked
```
Single binary. No daemon. No background process. Just reads config, evaluates rules, exits. Under 5ms.
## .cato.toml
Drop this in your project root. Commit to git. Your whole team gets the same protection.
```toml
# .cato.toml
[[rules]]
name = "protect-env"
file_match = ["*.env", "*.env.*"]
action = "deny"
message = "Environment files are protected"
[[rules]]
name = "protect-keys"
file_match = ["*.pem", "*.key", "*.p12"]
action = "deny"
message = "Key files are protected"
[[rules]]
name = "no-force-push"
command = "git"
args_contain = ["push", "--force"]
action = "deny"
message = "Force push is not allowed"
```
### Rule fields
| Field | Description |
|-------|-------------|
| `name` | Rule identifier |
| `group` | Optional grouping |
| `description` | Optional description |
| `command` | Command to match (string or array) |
| `args_contain` | Required substrings in command args |
| `args_match` | Glob patterns for args |
| `file_match` | Glob patterns for file paths |
| `path_in` | Only apply in these directories |
| `path_not` | Don't apply in these directories |
| `action` | `"allow"` or `"deny"` |
| `message` | Shown when blocked |
| `enabled` | Toggle without deleting |
First match wins. File rules always checked even when a command is allowed (catches `cat .env`).
## CLI
```bash
cato init # Create .cato.toml with defaults
cato check # Test if file/command is allowed
cato adapt # Set up agent hooks (claude-code, all)
cato audit # View audit log
cato audit -f # Follow new entries
cato audit -q denied # Filter entries
cato hook claude-code # Hook mode (called by agents)
cato hook check --op read --target .env # Generic hook
```
## Supported agents
| Agent | Status | Setup |
|-------|--------|-------|
| Claude Code | Supported | `cato adapt claude-code` |
| Cursor | Planned | Extension |
| VS Code Copilot | Planned | Extension |
| Aider | Planned | Config |
| Open Interpreter | Planned | Plugin |
### Adding your own adapter
Any tool that can run a command before executing can use Cato:
```bash
# Generic hook — exit 0 = allow, exit 1 = deny
cato hook check --op read --target /path/to/file
echo $?
# Or pipe JSON
echo '{"tool_name":"Read","tool_input":{"file_path":".env"}}' | cato hook claude-code
```
## Global rules
Rules in `~/.cato/config.toml` apply everywhere. Project `.cato.toml` rules are merged after (global deny can't be overridden by project allow).
## Audit log
Every check is logged to `~/.cato/audit.jsonl` as structured JSON:
```json
{"ts":"2026-04-26T00:00:00Z","op":"file","target":".env","cwd":"/project","agent":"claude-code","rule":"protect-env","decision":"denied","message":"Environment files are protected"}
```
Pipe to `jq`, send to Datadog, tail with `cato audit -f`.
## Building from source
```bash
git clone https://github.com/Harikrishnareddyl/cato.git
cd cato
cargo build --release
./target/release/cato init
./target/release/cato adapt claude-code
```
## Requirements
- macOS, Linux, or Windows (anywhere Rust compiles)
- For Claude Code: hooks support (built-in)
## License
MIT