PyMetrics accepts a public GitHub URL, clones the repository, runs radon/pylint/pydriller over every non-test Python file, and persists four levels of results (file / class / function / summary) to SQLite. Artifacts are streamed to object storage so the UI can offer immediate CSV and ZIP downloads.
https://github.com/<owner>/<repo>) and optionally a branch.pending, cloning, discovering, analyzing, git_analysis, generating, and done.Trigger an analysis:
curl -X POST http://localhost:8000/api/analyses \
-H "Content-Type: application/json" \
-d '{"repo_url": "https://github.com/pallets/flask", "branch": "main"}'
Pin a tag or commit:
curl -X POST http://localhost:8000/api/analyses \
-H "Content-Type: application/json" \
-d '{"repo_url": "https://github.com/psf/requests", "ref": "v2.32.3"}'
Stream progress:
curl -N http://localhost:8000/api/analyses/<id>/stream
Download the CSV for a granularity level:
curl -o file.csv http://localhost:8000/api/analyses/<id>/download/file
curl -o all.zip http://localhost:8000/api/analyses/<id>/download/all
On disk, completed runs are written under data/outputs/ with descriptive prefixes:
<repo>__<UTC timestamp>__ref-<branch-or-tag-or-sha>__a<analysis id>__sha-<commit>/
Example:
flask__20260503-002114__ref-main__a3__sha-1a2b3c4d5e6f/
List recent runs:
curl http://localhost:8000/api/analyses?limit=20
See /docs for the full OpenAPI schema.
| Setting | Effect on output |
|---|---|
CLONE_SHALLOW=false |
Enables git-history metrics (age_days, revisions, authors, avg_loc_added, avg_loc_deleted). |
PYLINT_ENABLED=false |
pylint_* columns are null. Analysis completes ~50 % faster. |
SKIP_TEST_FILES=true |
test_*.py, *_test.py, and files under tests/ are excluded. |
MAX_FILE_COUNT |
Discovery stops past this cap and logs a warning. |
MAX_REPO_SIZE_MB |
Rejects repositories that exceed the configured size after clone. |
The Insights tab lets you pass thresholds and see which files fail:
These are presentation-only — they do not influence the stored metrics.