AI Agent Governance Platform — enforces security and governance policies on AI agent tool calls. Invoked by agent hooks (Claude Code, Cursor, etc.) before tool execution; returns allow/block decisions via exit codes.
- Blocks secrets — scans every tool call for 38 types of secrets (API keys, private keys, credit cards, SSNs, etc.) before they can be written or sent
- Enforces rules — YAML-based governance rules can deny, require human approval, rate-limit, or audit any action
- Approval workflow — sensitive operations (credential file access, network transfers) pause and wait for explicit human sign-off
- Rate limiting — prevents runaway write/command loops per session
- Per-repo governance — drop a
.aegis/governance.yamlin any repo to override or extend global rules for that project - Full observability — every decision stored in SQLite with session, agent, tool, action, target, repo (cwd), result, and matched rule; queryable from the CLI
No. Claude Code's hooks let you run a script and optionally block a tool call — that's it. There is no:
- Rule engine or rule language
- Secret scanning
- Approval workflow
- Rate limiting
- Audit log or observability
- Per-repo or per-project policy
Aegis provides all of this as a single binary that wires into Claude Code (and other agents) via the existing hook mechanism.
git clone https://github.com/proxymoroniic/aegis
cd aegis
make build
sudo cp bin/aegis /usr/local/bin/aegis # or any directory on your PATHRun once after installation:
aegis setupThis writes the PreToolUse hook to ~/.claude/settings.json using the absolute binary path. To verify: cat ~/.claude/settings.json
Aegis exits 0 (allow) or 2 (block). Claude Code will abort the tool call on exit 2.
Copy the default governance rules to the config directory:
# macOS
mkdir -p ~/Library/Application\ Support/aegis
cp configs/governance.yaml ~/Library/Application\ Support/aegis/aegis evaluate <agent> <hook-type> # hook entry point — reads JSON from stdin
aegis scan <content> # scan text for secrets
aegis rules list # show loaded rules
aegis rules test <action-type> <target> # dry-run a target against rules
aegis pending # list pending approval requests
aegis approve <request-id> # approve a blocked request
aegis deny <request-id> # deny a blocked request
aegis logs [--session] [--action] [--target] [--agent] [--since] [--allowed/--denied] [--limit] [--format]
aegis sessions [--agent] [--since] [--limit] [--format]
aegis session <id> [--format]
aegis stats [--since] [--format]
aegis audit [--action] [--since] [--limit] [--format]
aegis version
Output formats: table (default), json, csv.
Every tool call Claude Code makes is recorded. Filter by any combination:
aegis logs # last 50 decisions
aegis logs --denied # only blocked actions
aegis logs --session <id> # one Claude Code session
aegis logs --action command_exec # all shell commands
aegis logs --target ".env" # anything touching .env files
aegis logs --target "rm -rf" --denied # blocked destructive commands
aegis logs --since 24h --format json # last 24h as JSONThe log table shows: TIMESTAMP, AGENT, REPO (directory name), TOOL (e.g. Bash, Read), ACTION (e.g. command_exec, file_read), TARGET (the actual command or file path), RESULT, and REASON.
| Rule | Action | What it blocks |
|---|---|---|
block-destructive-delete |
deny | rm -rf /, rm -rf ~, etc. |
block-system-modification |
deny | Writes to /etc/, /usr/, /System/ |
approve-credential-access |
require_approval | .env, .aws/, .ssh/, .gnupg/ |
approve-network-commands |
require_approval | curl --data, ssh, scp, rsync |
rate-limit-file-writes |
rate_limit | >100 file writes/min per session |
rate-limit-commands |
rate_limit | >50 commands/min per session |
audit-all-deletes |
audit | File deletions (allowed but logged) |
Create .aegis/governance.yaml in any repository to add repo-specific rules or override global ones. Per-repo rules are evaluated first; if no per-repo rule matches, global rules apply.
# .aegis/governance.yaml
rules:
# Override global: allow .env reads in this repo
- id: approve-credential-access
enabled: false
priority: 90
action: allow
conditions:
action_types: [file_read]
path_patterns: ['\.env']
# Repo-specific: block writes to generated directories
- id: block-generated-writes
enabled: true
priority: 80
action: deny
conditions:
action_types: [file_write]
path_patterns: ['^dist/', '^build/']
message: "Do not write to generated directories"A per-repo rule with the same id as a global rule replaces it for that repo. Rules with new IDs extend the global set.
Ready-made rule sets for common domains live in configs/profiles/. Drop one (or more) into .aegis/governance.yaml — or copy the rules you want into your global governance.yaml.
| Profile | File | What it covers |
|---|---|---|
| AWS | configs/profiles/aws.yaml |
IAM mutations, S3 deletion/public access, EC2 termination, RDS, CloudTrail, Secrets Manager |
| Terraform | configs/profiles/terraform.yaml |
terraform destroy, -auto-approve on prod, state mutations, hardcoded credentials |
| Database | configs/profiles/database.yaml |
DROP/TRUNCATE, DELETE/UPDATE without WHERE, schema changes, production connections, Redis FLUSHALL |
| Git | configs/profiles/git.yaml |
Force push to main, reset --hard, remote branch/tag deletion |
| Containers | configs/profiles/containers.yaml |
--privileged, host network/PID, Docker socket mount, kubectl prod namespace, RBAC mutations |
Use a profile for a specific repo:
# In your AWS infrastructure repo
mkdir -p .aegis
cp /usr/local/share/aegis/profiles/aws.yaml .aegis/governance.yaml
cp /usr/local/share/aegis/profiles/terraform.yaml .aegis/terraform-rules.yaml
# merge both into .aegis/governance.yaml, or load each directlyCombine multiple profiles into a single file:
# .aegis/governance.yaml — infrastructure repo: AWS + Terraform rules
rules:
# paste contents of aws.yaml rules: [...] here
# paste contents of terraform.yaml rules: [...] hereDefault locations:
- macOS:
~/Library/Application Support/aegis/ - Linux:
~/.config/aegis/(respectsXDG_CONFIG_HOME) - Override:
AEGIS_CONFIG_DIR,AEGIS_DATA_DIR
config.yaml:
rules_path: ~/.config/aegis/governance.yaml
scanner:
enabled: true
rate_limit:
enabled: true
approval:
enabled: true
default_timeout: 5m
observability:
enabled: true
fail_open: false # fail-closed by default (errors → block)1. Secret scan secrets in target+content? → BLOCK
2. Approval check valid existing approval? → ALLOW
3. Per-repo rules first matching rule wins → act on decision
4. Global rules first matching rule wins:
deny → BLOCK
require_approval → BLOCK + create request
rate_limit → BLOCK if window exceeded
audit → ALLOW (logged)
allow → ALLOW
5. Default → ALLOW
make build # build bin/aegis
make test # run all tests with race detector
make lint # golangci-lint
make fmt # gofmt + goimports