cc-audit
v0.4.2
Published
Audit Claude Code permissions across settings hierarchy
Maintainers
Readme
cc-audit
Audit and curate Claude Code permissions across settings layers.
Note: This is a TDD vibe-coded project. It is used in real-life but has not had extensive usage. The builtin rule files that classify commands into risk tiers are a convenience for catching foot-guns, not a security mechanism. They will not protect you from a determined or creative misuse of permissions. Always review permissions yourself before granting them.
Install
npm install -g cc-auditUsage
Audit permissions
cc-auditReads three settings layers and reports duplicates, sketchy patterns, broad wildcards, and contradictions:
- Global:
~/.claude/settings.json - Project:
.claude/settings.json - Local:
.claude/settings.local.json
Hoist permissions
Move permissions from settings.local.json to project or
global settings with an interactive TUI:
cc-audit --hoist # local -> project settings.json
cc-audit --hoist-global # local -> ~/.claude/settings.jsonEach permission can be set to Allow, Deny, or Skip. The auditor pre-classifies entries: safe patterns default to Allow, sketchy/broad patterns default to Deny.
Use --yes to skip the TUI and apply auditor defaults:
cc-audit --hoist --yesMulti-root hoist
Hoist local permissions from multiple project directories
into a single target. Useful when you have many git
worktrees or projects that accumulate separate
settings.local.json files:
cc-audit --hoist-global --scan # locals -> ~/.claude/settings.json
cc-audit --hoist-global --roots a,b,c # locals -> ~/.claude/settings.json
cc-audit --hoist --scan # locals -> cwd/.claude/settings.json
cc-audit --hoist --roots a,b,c # locals -> cwd/.claude/settings.jsonPermissions are deduplicated across roots. If the same permission appears in multiple locals, it is hoisted once. Allow/deny conflicts (same permission allowed in one root, denied in another) default to Skip for manual resolution.
Risk classification uses per-root rules (strictest wins).
To gather worktree roots for --roots:
git worktree list --porcelain | grep ^worktree | cut -d ' ' -f 2 | paste -sd, -The TUI supports filtering and batch actions:
/to filter entries by substringa/d/sto set Allow/Deny/Skip (batch with confirm when filter matches multiple entries)uto undo
Clean local permissions
Strip all permissions from settings.local.json (preserves
sandbox config):
cc-audit --cleanOptions
-r, --root <path> Project root directory (default: cwd)
--roots <paths> Comma-separated source roots for multi-root hoist
--scan [dir] Discover source roots in child dirs (default: cwd)
-f, --format <fmt> Output format: console, json
-y, --yes Skip interactive TUI, use auditor defaults
-q, --quiet Suppress non-essential outputWhat it detects
- Duplicates across layers (safe to remove from lower layer)
- Dangerous/forbidden patterns like
rm -rf,sudo,curl | sh - Broad wildcards like
Bash(*),Edit(*),Write(*) - Contradictions (same entry in both allow and deny)
Rules
cc-audit classifies permissions into four risk tiers:
| Tier | Hoist default | Meaning | |---------------|---------------|----------------------------------| | safe | Allow | Read-only or low-risk | | caution | Allow | Creates/modifies but reversible | | dangerous | Deny | Destructive or hard to reverse | | forbidden | Deny | Should never be auto-approved |
Permissions that don't match any rule default to Allow.
Classification is driven by JSON rule files loaded from three locations (highest precedence first):
- Project:
.cc-audit/rules/*.json - Global:
~/.cc-audit/rules/*.json - Builtin: shipped with the package
Rules are matched in precedence order and first match wins. This means your project or global rules always override builtins — if a builtin classifies a command as dangerous but your project rule says it's safe, the project rule wins.
Builtin rules
Rules are split by tool/provider, one file per authoritative doc source:
| File | Coverage |
|--------------|---------------------------------------|
| aws.json | Per-service command classification |
| git.json | git + gh CLI per-command |
| rust.json | Cargo per-command classification |
| bash.json | Dangerous shell patterns |
| broad.json | Tool-level wildcards |
The remaining provider files (gcloud, azure, kubernetes,
terraform, pulumi, heroku, flyio, vercel, netlify) are stubs
that flag the entire CLI as dangerous. PRs welcome to add
per-command classification — each file should cite its
authoritative doc source in the meta field.
Custom rules
Add project-specific or personal overrides:
// .cc-audit/rules/my-rules.json
{
"meta": {
"source": "https://docs.example.com/cli",
"verified": "2026-04-04"
},
"safe": [
{ "pattern": "Bash\\(mycli list", "reason": "read-only" }
],
"caution": [
{ "pattern": "Bash\\(mycli create", "reason": "creates resources" }
],
"dangerous": [
{ "pattern": "Bash\\(mycli delete", "reason": "destructive" }
],
"forbidden": [
{ "pattern": "Bash\\(mycli admin", "reason": "admin access" }
]
}Patterns are case-insensitive regular expressions matched
against permission strings (e.g. Bash(git push:*)). The
optional meta fields (source, verified) are for your
own traceability — they are not used by the tool.
License
MIT
