Metadata-Version: 2.4
Name: downscope
Version: 0.1.0
Summary: Least-privilege audit for Claude Code: see which permissions you actually use, which are dead weight, and which are dangerous - derived from your real session history.
Project-URL: Homepage, https://github.com/bogdancolceriu/downscope
Project-URL: Repository, https://github.com/bogdancolceriu/downscope
Project-URL: Issues, https://github.com/bogdancolceriu/downscope/issues
Author: Bogdan Colceriu
License: MIT
License-File: LICENSE
Keywords: ai-agents,audit,claude-code,least-privilege,permissions,security
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Requires-Dist: jinja2>=3.1
Requires-Dist: rich>=13.0
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: hypothesis>=6.100; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# 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.**

![downscope audit demo](docs/demo.svg)

*(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.

```bash
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:

```bash
downscope check --project-root . --baseline team-baseline.json --fail-on high
```

Exit codes: `0` clean, `1` violations, `2` usage error. GitHub Actions snippet:

```yaml
- name: Check agent permissions
  run: |
    pip install downscope
    downscope check --project-root . --baseline .claude/team-baseline.json
```

### `downscope diff` — drift over time

```bash
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)

1. **Settings-layer semantics.** Rules are matched with Claude Code's documented semantics: `Bash` glob forms (`git commit *`, `:*` word-boundary sugar), settings-source path anchoring (`/src/**` vs `//abs/path` vs `~/…`), WebFetch domain rules (`*.example.com` vs apex), MCP server globs, and layer provenance (user / project / local).
2. **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)

```bash
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
