downscope
Least-privilege audit for Claude Code permissions — derived from what your agent actually does, not from what you guessed it needs.
Your ~/.claude/projects directory already records every tool call your agent ever made. downscope reads that history together with your merged permission settings (user / project / local layers) and answers the questions nobody can answer by hand:
- USED — which allow rules your sessions actually exercised (counts + last-seen dates)
- UNUSED — which grants are dead weight and can be tightened
- MISSING — which commands you approve by hand all the time and deserve a rule
- RISK — ~30 deterministic checks over both your config (wildcard Bash allows, secrets-adjacent grants,
bypassPermissions) and your observed history (curl | sh, sudo, force-pushes, exfiltration patterns) - MCP — which configured MCP servers are actually used, and which are dead surface
Privacy: reads local files only. Zero network calls. Nothing leaves your machine.
(demo generated from a synthetic corpus — regenerate with python docs/make_demo.py)
Commands
downscope audit
The core command. Scans all local transcripts + settings and prints the coverage matrix, suggestions and risk findings.
downscope audit # terminal report
downscope audit --json # machine-readable, valid JSON on stdout
downscope audit --html report.html # self-contained HTML report (zero external assets)
downscope audit --emit-policy min.json # proposed minimal policy (reviewable fragment)
downscope audit --save-snapshot a.json # snapshot for later drift diffing
downscope audit --project-root . # include this repo's .claude/settings*.json + .mcp.json
The emitted policy is deliberately conservative: used grants are kept, unused grants are demoted to ask (never silently denied), frequent-but-safe patterns are promoted, interpreters (python, node, …) and anything already under ask/deny are never auto-promoted, and a small deny pack covers secrets paths and privilege escalation.
downscope check — CI gate
Fails the build when a repo's committed .claude/settings.json is risky or drifts from a team baseline:
downscope check --project-root . --baseline team-baseline.json --fail-on high
Exit codes: 0 clean, 1 violations, 2 usage error. GitHub Actions snippet:
- name: Check agent permissions
run: |
pip install downscope
downscope check --project-root . --baseline .claude/team-baseline.json
downscope diff — drift over time
downscope audit --save-snapshot before.json
# ... a week of sessions later ...
downscope audit --save-snapshot after.json
downscope diff before.json after.json
Shows rules added/removed, usage drift, new and resolved risk findings, and newly frequent uncovered commands.
How it differs from Claude Code's built-in /fewer-permission-prompts
/fewer-permission-prompts |
downscope |
|
|---|---|---|
| Adds read-only allows from history | yes | no (by design) |
| Finds unused grants | no | yes |
| Risk-scores config + history | no | ~30 deterministic rules |
| Emits minimal policy (shrink) | no | yes, reviewable |
| CI gate against a baseline | no | yes |
| Drift diffing over time | no | yes |
| MCP surface audit | no | yes |
The built-in skill reduces prompt fatigue by adding allows. downscope is the missing other half: the audit layer that shrinks, risk-scores and enforces. Use both.
How matching works (the two hard parts)
- Settings-layer semantics. Rules are matched with Claude Code's documented semantics:
Bashglob forms (git commit *,:*word-boundary sugar), settings-source path anchoring (/src/**vs//abs/pathvs~/…), WebFetch domain rules (*.example.comvs apex), MCP server globs, and layer provenance (user / project / local). - Chain-aware coverage. A chained command (
a && b | c) is only auto-approved when every link is covered, so coverage is decided per segment — with a quote-aware splitter that understands heredocs, comments, redirections and line continuations. Suggestions are generated only from the uncovered links.
Both parts are pinned by a fixture corpus and property-based tests (Hypothesis).
Install (development)
git clone https://github.com/bogdancolceriu/downscope && cd downscope
python -m venv .venv
# Windows: .venv\Scripts\activate POSIX: source .venv/bin/activate
pip install -e ".[dev]"
pytest -q && downscope audit
Tested on Windows, macOS and Linux via CI. Compatibility: transcript formats are undocumented internals; the parser skips unknown records gracefully and the fixture corpus pins the formats seen in Claude Code 2026 releases.
License
MIT
Metadata
Release files for downscope 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| downscope-0.1.0.tar.gz | 50.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| downscope-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 89.2 kB
Release files / downscope-0.1.0.tar.gz
| Download URL | downscope-0.1.0.tar.gz |
|---|---|
| Size | 50.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
336334697a2cd484af818843cf62c5ef7748cbff3fa46cf13db1ddfb05119d79
|
|
BLAKE2b-256 checksum How to use checksums |
5459156589bec17eb7a921f751c370e5a599d31b4f17bdfb80d64a833d61de1a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logRelease files / downscope-0.1.0-py3-none-any.whl
| Download URL | downscope-0.1.0-py3-none-any.whl |
|---|---|
| Size | 38.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
472ad23c3149bb157e41a15d57d438d04752ca4fe9dab779ae8fd3ef33937718
|
|
BLAKE2b-256 checksum How to use checksums |
8afd6c98ba9eaff822076b9e515b6255b75892cc0688880b6a5f03f47665c672
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency log