Unified code quality orchestration; linters, formatters, type checkers, and security analyzers in one CLI
Project description
Scrutiny
Unified code quality orchestration for Python projects.
Scrutiny runs Ruff (formatter + linter), Mypy, Radon, and Bandit in a single command with tiered strictness, opt-in pyproject.toml generation, context-aware defaults, and structured logging. Scrutiny respects your pyproject.toml as the authoritative source and never modifies it unless you explicitly ask. Configure once, enforce everywhere.
Installation
# All tools
pip install 'ks-scrutiny[all]'
# Specific tools only
pip install 'ks-scrutiny[ruff,mypy]'
# Core package only (install tools separately)
pip install ks-scrutiny
Configuration Precedence
Scrutiny follows a strict priority contract when building tool commands:
- Explicit scrutiny CLI overrides win over everything.
pyproject.tomlis authoritative when the CLI is silent.- Scrutiny's own defaults only fill in keys neither source has expressed.
Concretely: if you set fix = false under [tool.ruff], scrutiny
will not pass --fix to ruff. If you set exclude = [...] under
[tool.ruff], scrutiny will not emit its own --exclude flags,
letting ruff read the pyproject list natively. The equivalent rule
holds for mypy and bandit. Operational concerns that have no
pyproject equivalent (--no-cache, JSON output formatting) still
emit regardless.
Use --pyproject-only to suppress scrutiny defaults entirely;
tools then run with only your CLI overrides and pyproject settings.
Framework-specific rule families (--framework django, etc.) are
emitted as --extend-select so they supplement rather than replace
your pyproject select list when it exists.
pyproject.toml Management
Running scrutiny does not modify your pyproject.toml. It reads
whatever is there, respects it, and analyses your code. Config
generation is an explicit, one-time action via an opt-in flag.
Managed sections: [tool.ruff], [tool.mypy], [tool.bandit],
and optionally [tool.pytest.ini_options] + [tool.coverage.*]. All
other tool sections are never touched.
Generation flags
| Flag | Generates |
|---|---|
--generate-config |
[tool.ruff], [tool.mypy], [tool.bandit] |
--generate-config=test |
Above + [tool.pytest.ini_options] + [tool.coverage.*] |
--generate-config=all |
Above + pytest plugin addopts (pytest-cov, pytest-xdist) |
--generate-test-config |
Only [tool.pytest.ini_options] + [tool.coverage.*] |
--generate-test-config=plugins |
Only test sections with plugin addopts |
--generate-config and --generate-test-config are mutually
exclusive. Combine either with --override-config to replace
existing managed sections instead of merging.
Merge vs override
| Scenario | Default (merge) | With --override-config |
|---|---|---|
| Key exists in your file | Preserved | Replaced with generated |
| Key missing from your file | Added | Added |
| Unmanaged tool sections | Untouched | Untouched |
Generated settings are tier-aware; the rules, strictness, and thresholds written to your config match your selected tier (essential, standard, strict, or insane).
Quick Start
# Run analysis with the standard tier (default); read-only, does not modify files
scrutiny
# Bootstrap managed [tool.*] sections on first use
scrutiny --generate-config
# Run on a specific directory
scrutiny src/
# Opt into auto-fix and formatting
scrutiny --fix --tool ruff
# Strict tier for maximum rigor
scrutiny --strict
# Check tool availability
scrutiny --doctor
Output Example
======================================================================
Code Quality Analysis
Project: my-project
Tools: ruff_linter, mypy, radon, bandit
Tier: standard
Security: enabled
Context: cli
Mode: standard
Framework: none
======================================================================
Running ruff_linter...
[ruff_linter]
Files: 12
Issues: 0
Time: 0.03s
Checked: 22 lint rule groups
Result: no issues found
Running mypy...
[mypy]
Files: 12
Issues: 0
Time: 0.45s
Checked: warn unreachable, ignore missing imports
Result: no type errors
Running radon...
[radon]
Files: 12
Issues: 0
Time: 0.08s
Checked: cyclomatic complexity (threshold C, max score 20)
Result: all functions within threshold
Running bandit...
[bandit]
Files: 12
Issues: 0
Time: 0.15s
Checked: security (MEDIUM+ severity, HIGH+ confidence)
Result: no findings
======================================================================
Script Code: 0
All checks passed (12 files, 0.73s)
ruff_linter ... passed
mypy ... passed
radon ... passed
bandit ... passed
======================================================================
Configuration Tiers
| Tier | Description | Use Case |
|---|---|---|
--essential |
Core correctness only | Legacy codebases, quick checks |
--standard |
Quality + correctness (default) | Production-ready code |
--strict |
Maximum rigor | Enforced style and best practices |
--insane |
Every rule enabled | Bulletproof but noisy |
Each tier includes all rules from the tier below it.
CLI Flags (Summary)
| Flag | Description |
|---|---|
--tool ruff|mypy|radon|bandit |
Run only specified tool(s) |
--essential / --standard / --strict / --insane |
Select quality tier |
--fix / --check-only |
Enable/disable auto-fix |
--parallel / --no-parallel |
Parallel tool execution |
--generate-config[=test|all] |
Create/merge managed pyproject sections |
--generate-test-config[=plugins] |
Create/merge only test sections |
--override-config |
Replace (not merge) managed sections on generation |
--pyproject-only |
Use pyproject + CLI only; bypass scrutiny defaults |
--show-config |
Display effective configuration |
--doctor |
Check tool availability |
-q / -v / --detailed |
Output verbosity |
See CLI Reference for the complete reference.
Documentation
- CLI Reference - All flags with examples
- Configuration - Tiers, tool settings, exclusions
- Architecture - Package structure and data flow
- API Reference - Public API for programmatic use
License
See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ks_scrutiny-4.0.1.tar.gz.
File metadata
- Download URL: ks_scrutiny-4.0.1.tar.gz
- Upload date:
- Size: 217.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fd386eadc50b07857bd31cb54806e6dea88b201629ac5f8f61269bc554649cb
|
|
| MD5 |
93b084e09a313c7fe17ce9fab097ddd3
|
|
| BLAKE2b-256 |
a5c95b0b6e5512363d2a09ba0e02b318287520b8f4b5a359c950df58645265b0
|
File details
Details for the file ks_scrutiny-4.0.1-py3-none-any.whl.
File metadata
- Download URL: ks_scrutiny-4.0.1-py3-none-any.whl
- Upload date:
- Size: 115.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50097fd01b0d3996e4660249eecb31eb1cd0005106366b1370fc87aeb1b04ab7
|
|
| MD5 |
6187c1d89b5b1a189686f2f1a0080b5a
|
|
| BLAKE2b-256 |
caedc255438972edbba289eec56acb70adea744e0bb18f5b01311471e1c6ed0b
|