repoglance 0.2.2__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. repoglance-0.4.0/.github/ISSUE_TEMPLATE/bug_report.yml +41 -0
  2. repoglance-0.4.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  3. repoglance-0.4.0/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
  4. repoglance-0.4.0/.github/PULL_REQUEST_TEMPLATE.md +16 -0
  5. repoglance-0.4.0/.repoglance-badge.json +1 -0
  6. repoglance-0.4.0/CHANGELOG.md +84 -0
  7. repoglance-0.4.0/CODE_OF_CONDUCT.md +35 -0
  8. repoglance-0.4.0/Dockerfile +10 -0
  9. {repoglance-0.2.2 → repoglance-0.4.0}/PKG-INFO +58 -15
  10. {repoglance-0.2.2 → repoglance-0.4.0}/README.md +55 -14
  11. repoglance-0.4.0/SECURITY.md +27 -0
  12. {repoglance-0.2.2 → repoglance-0.4.0}/action.yml +22 -1
  13. {repoglance-0.2.2 → repoglance-0.4.0}/assets/badge.svg +7 -7
  14. repoglance-0.4.0/assets/demo.svg +391 -0
  15. repoglance-0.4.0/assets/demo.tape +17 -0
  16. repoglance-0.4.0/assets/showcase/flask.svg +312 -0
  17. repoglance-0.4.0/assets/showcase/httpie.svg +351 -0
  18. repoglance-0.4.0/assets/showcase/requests.svg +326 -0
  19. repoglance-0.4.0/docs/index.md +35 -0
  20. repoglance-0.4.0/editors/vscode/README.md +19 -0
  21. repoglance-0.4.0/editors/vscode/extension.js +63 -0
  22. repoglance-0.4.0/editors/vscode/package.json +26 -0
  23. repoglance-0.4.0/integrations/gitlab-ci.yml +13 -0
  24. repoglance-0.4.0/mkdocs.yml +7 -0
  25. repoglance-0.4.0/packaging/homebrew/repoglance.rb +34 -0
  26. {repoglance-0.2.2 → repoglance-0.4.0}/pyproject.toml +3 -1
  27. {repoglance-0.2.2 → repoglance-0.4.0}/src/repoglance/__init__.py +1 -1
  28. repoglance-0.4.0/src/repoglance/cache.py +59 -0
  29. repoglance-0.4.0/src/repoglance/cli.py +242 -0
  30. repoglance-0.4.0/src/repoglance/complexity.py +129 -0
  31. repoglance-0.4.0/src/repoglance/config.py +55 -0
  32. repoglance-0.4.0/src/repoglance/dedup.py +70 -0
  33. {repoglance-0.2.2 → repoglance-0.4.0}/src/repoglance/gitinfo.py +20 -0
  34. {repoglance-0.2.2 → repoglance-0.4.0}/src/repoglance/metrics.py +22 -0
  35. repoglance-0.4.0/src/repoglance/plugins.py +43 -0
  36. {repoglance-0.2.2 → repoglance-0.4.0}/src/repoglance/report.py +173 -3
  37. {repoglance-0.2.2 → repoglance-0.4.0}/src/repoglance/scanner.py +146 -31
  38. repoglance-0.4.0/src/repoglance/vendored.py +57 -0
  39. repoglance-0.4.0/tests/test_v030.py +108 -0
  40. repoglance-0.4.0/tests/test_v040.py +70 -0
  41. repoglance-0.2.2/.repoglance-badge.json +0 -1
  42. repoglance-0.2.2/CHANGELOG.md +0 -41
  43. repoglance-0.2.2/assets/demo.svg +0 -329
  44. repoglance-0.2.2/assets/showcase/flask.svg +0 -268
  45. repoglance-0.2.2/assets/showcase/httpie.svg +0 -311
  46. repoglance-0.2.2/assets/showcase/requests.svg +0 -290
  47. repoglance-0.2.2/src/repoglance/cli.py +0 -90
  48. repoglance-0.2.2/src/repoglance/complexity.py +0 -85
  49. {repoglance-0.2.2 → repoglance-0.4.0}/.github/workflows/ci.yml +0 -0
  50. {repoglance-0.2.2 → repoglance-0.4.0}/.github/workflows/release.yml +0 -0
  51. {repoglance-0.2.2 → repoglance-0.4.0}/.github/workflows/repoglance.yml +0 -0
  52. {repoglance-0.2.2 → repoglance-0.4.0}/.gitignore +0 -0
  53. {repoglance-0.2.2 → repoglance-0.4.0}/.pre-commit-hooks.yaml +0 -0
  54. {repoglance-0.2.2 → repoglance-0.4.0}/CONTRIBUTING.md +0 -0
  55. {repoglance-0.2.2 → repoglance-0.4.0}/LICENSE +0 -0
  56. {repoglance-0.2.2 → repoglance-0.4.0}/RELEASING.md +0 -0
  57. {repoglance-0.2.2 → repoglance-0.4.0}/src/repoglance/__main__.py +0 -0
  58. {repoglance-0.2.2 → repoglance-0.4.0}/src/repoglance/badge.py +0 -0
  59. {repoglance-0.2.2 → repoglance-0.4.0}/src/repoglance/languages.py +0 -0
  60. {repoglance-0.2.2 → repoglance-0.4.0}/tests/test_cli.py +0 -0
  61. {repoglance-0.2.2 → repoglance-0.4.0}/tests/test_complexity.py +0 -0
  62. {repoglance-0.2.2 → repoglance-0.4.0}/tests/test_features.py +0 -0
  63. {repoglance-0.2.2 → repoglance-0.4.0}/tests/test_scanner.py +0 -0
  64. {repoglance-0.2.2 → repoglance-0.4.0}/tests/test_scanner_extra.py +0 -0
@@ -0,0 +1,41 @@
1
+ name: Bug report
2
+ description: Something in repoglance is broken or wrong
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: Thanks for taking the time to file a bug! Please fill in the details below.
8
+ - type: input
9
+ id: version
10
+ attributes:
11
+ label: repoglance version
12
+ description: Output of `repoglance --version`
13
+ placeholder: "repoglance, version 0.2.2"
14
+ validations:
15
+ required: true
16
+ - type: input
17
+ id: python
18
+ attributes:
19
+ label: Python version & OS
20
+ placeholder: "Python 3.11 on macOS 14"
21
+ validations:
22
+ required: true
23
+ - type: textarea
24
+ id: what-happened
25
+ attributes:
26
+ label: What happened?
27
+ description: What did you run, what did you expect, and what did you get?
28
+ placeholder: |
29
+ Command: repoglance .
30
+ Expected: ...
31
+ Actual: ...
32
+ validations:
33
+ required: true
34
+ - type: textarea
35
+ id: traceback
36
+ attributes:
37
+ label: Traceback / output
38
+ description: Paste any error output. This will be rendered as code.
39
+ render: shell
40
+ validations:
41
+ required: false
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Question or discussion
4
+ url: https://github.com/SRJ-ai/repoglance/discussions
5
+ about: Ask a question or share an idea before opening an issue.
@@ -0,0 +1,24 @@
1
+ name: Feature request
2
+ description: Suggest an idea for repoglance
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes:
8
+ label: What problem would this solve?
9
+ description: Describe the use case, not just the feature.
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: proposal
14
+ attributes:
15
+ label: Proposed solution
16
+ description: What would you like repoglance to do?
17
+ validations:
18
+ required: false
19
+ - type: textarea
20
+ id: alternatives
21
+ attributes:
22
+ label: Alternatives considered
23
+ validations:
24
+ required: false
@@ -0,0 +1,16 @@
1
+ <!-- Thanks for contributing to repoglance! -->
2
+
3
+ ## What does this change?
4
+
5
+ <!-- A short description of the change and why. -->
6
+
7
+ ## Checklist
8
+
9
+ - [ ] Tests added or updated (`python -m pytest -q` passes)
10
+ - [ ] Docs / README updated if behavior changed
11
+ - [ ] Runtime deps still limited to `rich` + `click`
12
+ - [ ] For a new language: added to `EXT_LANG` (and comment prefixes if relevant)
13
+
14
+ ## Related issues
15
+
16
+ <!-- e.g. Closes #123 -->
@@ -0,0 +1 @@
1
+ {"schemaVersion": 1, "label": "repoglance", "message": "2.7k loc \u2022 Python", "color": "blue"}
@@ -0,0 +1,84 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format is based on
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
5
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.4.0] - 2026-08-01
8
+
9
+ ### Added
10
+ - **Duplicate-code detection** (`--duplicates`): sliding line-window hashing
11
+ surfaces copy-paste blocks and a duplication percentage.
12
+ - **Vendored/generated detection**: minified bundles, `_pb2.py`, lock files,
13
+ `node_modules`, and files marked `@generated` are excluded by default;
14
+ `--include-vendored` keeps them.
15
+ - **Ownership** (`--owners`): attributes the top complexity hotspots to authors
16
+ via `git blame`.
17
+ - **Incremental cache** (`--cache <file>`): unchanged files are reused across
18
+ runs by mtime + size, speeding up repeated scans.
19
+ - **Plugin API**: third-party packages can register metrics under the
20
+ `repoglance.metrics` entry-point group; results appear under `plugins`.
21
+ - **Watch mode** (`--watch`): re-render the report whenever files change.
22
+ - Homebrew formula template and a minimal VS Code extension (Problems panel).
23
+
24
+ ### Fixed
25
+ - Git subprocesses now decode as UTF-8, fixing crashes on non-Latin-1 blame
26
+ output on Windows.
27
+
28
+ ## [0.3.0] - 2026-08-01
29
+
30
+ ### Added
31
+ - **Real cyclomatic complexity across 15+ languages** via `lizard` (C/C++, Java,
32
+ C#, JavaScript, TypeScript, Go, Rust, Ruby, PHP, Swift, Kotlin, Python and
33
+ more). Python keeps an AST fallback; a keyword heuristic remains as last
34
+ resort. Complexity for non-Python languages is now trustworthy, not a guess.
35
+ - **Maintainability index** (0–100), approximate Microsoft MI from complexity,
36
+ size and token counts.
37
+ - **Diff mode** `--since <rev>`: analyze only files changed since a git ref —
38
+ ideal for PRs. The Action exposes it via `diff-base`.
39
+ - **Baselines & regression ratchet**: `--baseline` snapshots a report;
40
+ `--compare` shows health/complexity/TODO/LOC deltas; `--fail-on-regression`
41
+ fails only on new or worse complexity.
42
+ - **SARIF output** (`--sarif`) for GitHub code scanning; the Action can upload
43
+ it (`sarif: true`) so hotspots appear inline on the Files changed tab.
44
+ - **CSV output** (`--csv`) and a **per-directory rollup** (report + JSON).
45
+ - **Config file**: `.repoglance.toml` or `[tool.repoglance]` in pyproject.
46
+ - **Glob include/exclude** (`--include` / `--exclude`) beyond directory names.
47
+ - **Parallel scanning** (`--jobs`) via a thread pool.
48
+ - Docker image, GitLab CI template, and mkdocs docs scaffold.
49
+
50
+ ## [0.2.2] - 2026-08-01
51
+
52
+ ### Added
53
+ - Respect the repository's `.gitignore`: when scanning a git repo, the file
54
+ list comes from `git ls-files` so ignored files are excluded (matches the
55
+ behavior of `tokei`/`scc`). Non-git directories still use a pruned walk.
56
+ - Count C-style `/* ... */` block comments when classifying lines, improving the
57
+ comment ratio (and therefore the health score) for C-family languages.
58
+ - Expanded test suite: CLI end-to-end (`click` runner), `.gitignore` handling,
59
+ block comments, and inline complexity scoring.
60
+
61
+ ### Changed
62
+ - Every file is now read exactly once. Complexity is computed during the scan
63
+ from the text already in memory instead of re-reading every file in a second
64
+ pass — roughly halving I/O on large repositories.
65
+
66
+ ## [0.2.1] - 2026-08-01
67
+
68
+ ### Changed
69
+ - Marketplace listing name set to a globally-unique title.
70
+
71
+ ## [0.2.0] - 2026-08-01
72
+
73
+ ### Changed
74
+ - Renamed the PyPI package and CLI to **repoglance** (the GitHub repository is
75
+ unchanged). Only line-comment TODO markers are counted, avoiding false
76
+ positives from prose and marker lists.
77
+
78
+ ## [0.1.0] - 2026-08-01
79
+
80
+ ### Added
81
+ - Initial release: rich terminal report (languages, complexity hotspots, TODO
82
+ tracker, biggest files, git activity), health score, JSON/Markdown/SVG/HTML
83
+ output, self-contained and dynamic badges, CI gate, GitHub Action, and
84
+ pre-commit hook.
@@ -0,0 +1,35 @@
1
+ # Code of Conduct
2
+
3
+ ## Our pledge
4
+
5
+ We as members, contributors, and maintainers pledge to make participation in
6
+ the repoglance community a harassment-free experience for everyone, regardless
7
+ of age, body size, visible or invisible disability, ethnicity, sex
8
+ characteristics, gender identity and expression, level of experience,
9
+ education, socio-economic status, nationality, personal appearance, race,
10
+ religion, or sexual identity and orientation.
11
+
12
+ ## Our standards
13
+
14
+ Examples of behavior that contributes to a positive environment:
15
+
16
+ - Being respectful of differing opinions, viewpoints, and experiences
17
+ - Giving and gracefully accepting constructive feedback
18
+ - Focusing on what is best for the community
19
+ - Showing empathy toward other community members
20
+
21
+ Unacceptable behavior includes harassment, insulting or derogatory comments,
22
+ personal or political attacks, publishing others' private information, and
23
+ other conduct which could reasonably be considered inappropriate.
24
+
25
+ ## Enforcement
26
+
27
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
28
+ reported to the project maintainers. All complaints will be reviewed and
29
+ investigated promptly and fairly. Maintainers are obligated to respect the
30
+ privacy and security of the reporter of any incident.
31
+
32
+ ## Attribution
33
+
34
+ This Code of Conduct is adapted from the
35
+ [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
@@ -0,0 +1,10 @@
1
+ # Minimal image to run repoglance against a mounted repository.
2
+ # docker build -t repoglance .
3
+ # docker run --rm -v "$PWD:/repo" repoglance /repo
4
+ FROM python:3.12-slim
5
+
6
+ RUN pip install --no-cache-dir repoglance
7
+
8
+ WORKDIR /repo
9
+ ENTRYPOINT ["repoglance"]
10
+ CMD ["."]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: repoglance
3
- Version: 0.2.2
3
+ Version: 0.4.0
4
4
  Summary: Instant, gorgeous insight into any code repository — languages, complexity hotspots, TODOs and git activity in one terminal command.
5
5
  Project-URL: Homepage, https://github.com/SRJ-ai/repoglance
6
6
  Project-URL: Repository, https://github.com/SRJ-ai/repoglance
@@ -21,7 +21,9 @@ Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Topic :: Software Development :: Quality Assurance
22
22
  Requires-Python: >=3.9
23
23
  Requires-Dist: click>=8.0
24
+ Requires-Dist: lizard>=1.17
24
25
  Requires-Dist: rich>=13.0
26
+ Requires-Dist: tomli>=2.0; python_version < '3.11'
25
27
  Provides-Extra: dev
26
28
  Requires-Dist: pytest-cov; extra == 'dev'
27
29
  Requires-Dist: pytest>=7.0; extra == 'dev'
@@ -37,10 +39,11 @@ Point it at any folder. In under a second you get a beautiful terminal report:
37
39
  language breakdown, complexity hotspots, TODO tracker, biggest files, and git
38
40
  activity. **Zero config. Zero API keys. Zero telemetry.**
39
41
 
42
+ [![PyPI](https://img.shields.io/pypi/v/repoglance.svg)](https://pypi.org/project/repoglance/)
43
+ [![Downloads](https://img.shields.io/pypi/dm/repoglance.svg)](https://pypi.org/project/repoglance/)
40
44
  [![CI](https://github.com/SRJ-ai/repoglance/actions/workflows/ci.yml/badge.svg)](https://github.com/SRJ-ai/repoglance/actions/workflows/ci.yml)
41
- [![Python](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/)
45
+ [![Python](https://img.shields.io/pypi/pyversions/repoglance.svg)](https://pypi.org/project/repoglance/)
42
46
  [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
43
- [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
44
47
  [![repoglance](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/SRJ-ai/repoglance/main/.repoglance-badge.json)](https://github.com/SRJ-ai/repoglance)
45
48
 
46
49
  </div>
@@ -69,9 +72,9 @@ repoglance run against well-known projects (click to view the full report):
69
72
 
70
73
  | Project | Files | Lines of code | Health |
71
74
  |---|--:|--:|:--:|
72
- | [flask](assets/showcase/flask.svg) | 209 | 25,293 | D (64) |
73
- | [httpie](assets/showcase/httpie.svg) | 236 | 20,114 | D (62) |
74
- | [requests](assets/showcase/requests.svg) | 89 | 13,785 | C (70) |
75
+ | [flask](assets/showcase/flask.svg) | 207 | 25,266 | D (67) |
76
+ | [httpie](assets/showcase/httpie.svg) | 234 | 20,023 | D (66) |
77
+ | [requests](assets/showcase/requests.svg) | 88 | 13,709 | C (70) |
75
78
 
76
79
  <div align="center">
77
80
 
@@ -97,12 +100,21 @@ pipx run repoglance .
97
100
  repoglance # analyze current directory
98
101
  repoglance path/to/repo # analyze another repo
99
102
  repoglance --json # machine-readable output for scripts / CI
103
+ repoglance --csv # per-file CSV
104
+ repoglance --sarif # SARIF for GitHub code scanning
100
105
  repoglance --svg report.svg # export a vector report
101
106
  repoglance --html report.html # export a browser report
102
107
  repoglance --badge badge.svg # export an embeddable badge
103
- repoglance --ci --max-complexity 25 # fail CI on hotspots
104
- repoglance --no-git # skip git history
105
- repoglance --ignore dist --ignore fixtures
108
+ repoglance --since origin/main # only files changed since a revision
109
+ repoglance --baseline base.json # snapshot now
110
+ repoglance --compare base.json --fail-on-regression # fail on new complexity
111
+ repoglance --ci --fail-under 70 --max-complexity 25 # gate a build
112
+ repoglance --include "src/**" --exclude "**/*_pb2.py" # glob filters
113
+ repoglance --duplicates # detect copy-paste blocks
114
+ repoglance --owners # attribute hotspots to authors (git blame)
115
+ repoglance --cache .rg.cache # incremental cache for fast repeat runs
116
+ repoglance --watch # live re-render on file changes
117
+ repoglance --no-git --jobs 8
106
118
  ```
107
119
 
108
120
  ### JSON output
@@ -118,11 +130,18 @@ repoglance --json | jq '.languages.Python.code'
118
130
  | Section | What you get |
119
131
  |---|---|
120
132
  | **Languages** | Lines of code per language, ranked, with % bars |
121
- | **Complexity hotspots** | Per-function cyclomatic complexity (Python via AST; heuristic for other langs) |
133
+ | **Complexity hotspots** | Real per-function cyclomatic complexity across 15+ languages (C/C++, Java, C#, JS, TS, Go, Rust, Ruby, PHP, Swift, Kotlin, Python…) via [lizard](https://github.com/terryyin/lizard) |
134
+ | **Maintainability index** | Approximate MI (0–100) from complexity, size and token counts |
135
+ | **Duplicate code** | Copy-paste blocks across files, with a duplication % |
122
136
  | **TODO tracker** | Every `TODO` / `FIXME` / `HACK` / `XXX` / `BUG` with file:line |
123
- | **Biggest files** | The files most likely to need splitting |
137
+ | **Biggest files & directories** | Where the mass and the worst complexity live |
138
+ | **Ownership** | Which author owns each hotspot (`--owners`, git blame) |
124
139
  | **Git activity** | Top authors, most-churned files, active days, project lifespan |
125
140
 
141
+ Vendored and generated files (minified bundles, `_pb2.py`, `node_modules`, files
142
+ marked `@generated`) are detected and excluded by default — pass
143
+ `--include-vendored` to keep them.
144
+
126
145
  Binary files, `node_modules`, `.venv`, build dirs and friends are skipped
127
146
  automatically.
128
147
 
@@ -135,14 +154,17 @@ gives you artifacts you can put in a PR or a README.
135
154
  | | repoglance | tokei | scc | cloc |
136
155
  |---|:---:|:---:|:---:|:---:|
137
156
  | Lines-of-code by language | ✅ | ✅ | ✅ | ✅ |
138
- | Complexity hotspots (per function) | ✅ | ❌ | ⚠️ file-level | ❌ |
157
+ | Per-function complexity (15+ langs) | ✅ | ❌ | ⚠️ file-level | ❌ |
158
+ | Maintainability index | ✅ | ❌ | ❌ | ❌ |
139
159
  | TODO / FIXME tracker | ✅ | ❌ | ❌ | ❌ |
140
160
  | Git activity (authors, churn) | ✅ | ❌ | ❌ | ❌ |
141
- | JSON output | ✅ | ✅ | ✅ | |
161
+ | Respects `.gitignore` | ✅ | ✅ | ✅ | |
162
+ | JSON / CSV / **SARIF** output | ✅ | ⚠️ | ⚠️ | ⚠️ |
142
163
  | **HTML / SVG report export** | ✅ | ❌ | ❌ | ❌ |
143
164
  | **Embeddable repo badge** | ✅ | ❌ | ❌ | ❌ |
144
- | **CI gate (`--max-complexity`)** | ✅ | ❌ | ❌ | ❌ |
145
- | Zero install deps beyond one `pip` | ✅ | (binary) | (binary) | (perl) |
165
+ | **Diff mode (`--since`) + baselines** | ✅ | ❌ | ❌ | ❌ |
166
+ | **CI gate + regression ratchet** | ✅ | | | |
167
+ | **Config file** (`[tool.repoglance]`) | ✅ | ✅ | ❌ | ❌ |
146
168
 
147
169
  ## Share it: badges & reports
148
170
 
@@ -235,6 +257,27 @@ repoglance --badge-json .repoglance-badge.json # commit this file
235
257
  repoglance --md # paste into a PR, wiki, or Slack
236
258
  ```
237
259
 
260
+ ### Configuration file
261
+
262
+ Set defaults once via `.repoglance.toml` or a `[tool.repoglance]` table in
263
+ `pyproject.toml` (CLI flags always win):
264
+
265
+ ```toml
266
+ [tool.repoglance]
267
+ exclude = ["**/*_pb2.py", "vendor/**"]
268
+ max_complexity = 25
269
+ fail_under = 70
270
+ ```
271
+
272
+ ### Docker & GitLab
273
+
274
+ ```bash
275
+ docker run --rm -v "$PWD:/repo" repoglance /repo
276
+ ```
277
+
278
+ A ready-to-copy GitLab CI job lives in
279
+ [`integrations/gitlab-ci.yml`](integrations/gitlab-ci.yml).
280
+
238
281
  ## Design goals
239
282
 
240
283
  - **Fast** — a single pass, no external services.
@@ -8,10 +8,11 @@ Point it at any folder. In under a second you get a beautiful terminal report:
8
8
  language breakdown, complexity hotspots, TODO tracker, biggest files, and git
9
9
  activity. **Zero config. Zero API keys. Zero telemetry.**
10
10
 
11
+ [![PyPI](https://img.shields.io/pypi/v/repoglance.svg)](https://pypi.org/project/repoglance/)
12
+ [![Downloads](https://img.shields.io/pypi/dm/repoglance.svg)](https://pypi.org/project/repoglance/)
11
13
  [![CI](https://github.com/SRJ-ai/repoglance/actions/workflows/ci.yml/badge.svg)](https://github.com/SRJ-ai/repoglance/actions/workflows/ci.yml)
12
- [![Python](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/)
14
+ [![Python](https://img.shields.io/pypi/pyversions/repoglance.svg)](https://pypi.org/project/repoglance/)
13
15
  [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
14
- [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
15
16
  [![repoglance](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/SRJ-ai/repoglance/main/.repoglance-badge.json)](https://github.com/SRJ-ai/repoglance)
16
17
 
17
18
  </div>
@@ -40,9 +41,9 @@ repoglance run against well-known projects (click to view the full report):
40
41
 
41
42
  | Project | Files | Lines of code | Health |
42
43
  |---|--:|--:|:--:|
43
- | [flask](assets/showcase/flask.svg) | 209 | 25,293 | D (64) |
44
- | [httpie](assets/showcase/httpie.svg) | 236 | 20,114 | D (62) |
45
- | [requests](assets/showcase/requests.svg) | 89 | 13,785 | C (70) |
44
+ | [flask](assets/showcase/flask.svg) | 207 | 25,266 | D (67) |
45
+ | [httpie](assets/showcase/httpie.svg) | 234 | 20,023 | D (66) |
46
+ | [requests](assets/showcase/requests.svg) | 88 | 13,709 | C (70) |
46
47
 
47
48
  <div align="center">
48
49
 
@@ -68,12 +69,21 @@ pipx run repoglance .
68
69
  repoglance # analyze current directory
69
70
  repoglance path/to/repo # analyze another repo
70
71
  repoglance --json # machine-readable output for scripts / CI
72
+ repoglance --csv # per-file CSV
73
+ repoglance --sarif # SARIF for GitHub code scanning
71
74
  repoglance --svg report.svg # export a vector report
72
75
  repoglance --html report.html # export a browser report
73
76
  repoglance --badge badge.svg # export an embeddable badge
74
- repoglance --ci --max-complexity 25 # fail CI on hotspots
75
- repoglance --no-git # skip git history
76
- repoglance --ignore dist --ignore fixtures
77
+ repoglance --since origin/main # only files changed since a revision
78
+ repoglance --baseline base.json # snapshot now
79
+ repoglance --compare base.json --fail-on-regression # fail on new complexity
80
+ repoglance --ci --fail-under 70 --max-complexity 25 # gate a build
81
+ repoglance --include "src/**" --exclude "**/*_pb2.py" # glob filters
82
+ repoglance --duplicates # detect copy-paste blocks
83
+ repoglance --owners # attribute hotspots to authors (git blame)
84
+ repoglance --cache .rg.cache # incremental cache for fast repeat runs
85
+ repoglance --watch # live re-render on file changes
86
+ repoglance --no-git --jobs 8
77
87
  ```
78
88
 
79
89
  ### JSON output
@@ -89,11 +99,18 @@ repoglance --json | jq '.languages.Python.code'
89
99
  | Section | What you get |
90
100
  |---|---|
91
101
  | **Languages** | Lines of code per language, ranked, with % bars |
92
- | **Complexity hotspots** | Per-function cyclomatic complexity (Python via AST; heuristic for other langs) |
102
+ | **Complexity hotspots** | Real per-function cyclomatic complexity across 15+ languages (C/C++, Java, C#, JS, TS, Go, Rust, Ruby, PHP, Swift, Kotlin, Python…) via [lizard](https://github.com/terryyin/lizard) |
103
+ | **Maintainability index** | Approximate MI (0–100) from complexity, size and token counts |
104
+ | **Duplicate code** | Copy-paste blocks across files, with a duplication % |
93
105
  | **TODO tracker** | Every `TODO` / `FIXME` / `HACK` / `XXX` / `BUG` with file:line |
94
- | **Biggest files** | The files most likely to need splitting |
106
+ | **Biggest files & directories** | Where the mass and the worst complexity live |
107
+ | **Ownership** | Which author owns each hotspot (`--owners`, git blame) |
95
108
  | **Git activity** | Top authors, most-churned files, active days, project lifespan |
96
109
 
110
+ Vendored and generated files (minified bundles, `_pb2.py`, `node_modules`, files
111
+ marked `@generated`) are detected and excluded by default — pass
112
+ `--include-vendored` to keep them.
113
+
97
114
  Binary files, `node_modules`, `.venv`, build dirs and friends are skipped
98
115
  automatically.
99
116
 
@@ -106,14 +123,17 @@ gives you artifacts you can put in a PR or a README.
106
123
  | | repoglance | tokei | scc | cloc |
107
124
  |---|:---:|:---:|:---:|:---:|
108
125
  | Lines-of-code by language | ✅ | ✅ | ✅ | ✅ |
109
- | Complexity hotspots (per function) | ✅ | ❌ | ⚠️ file-level | ❌ |
126
+ | Per-function complexity (15+ langs) | ✅ | ❌ | ⚠️ file-level | ❌ |
127
+ | Maintainability index | ✅ | ❌ | ❌ | ❌ |
110
128
  | TODO / FIXME tracker | ✅ | ❌ | ❌ | ❌ |
111
129
  | Git activity (authors, churn) | ✅ | ❌ | ❌ | ❌ |
112
- | JSON output | ✅ | ✅ | ✅ | |
130
+ | Respects `.gitignore` | ✅ | ✅ | ✅ | |
131
+ | JSON / CSV / **SARIF** output | ✅ | ⚠️ | ⚠️ | ⚠️ |
113
132
  | **HTML / SVG report export** | ✅ | ❌ | ❌ | ❌ |
114
133
  | **Embeddable repo badge** | ✅ | ❌ | ❌ | ❌ |
115
- | **CI gate (`--max-complexity`)** | ✅ | ❌ | ❌ | ❌ |
116
- | Zero install deps beyond one `pip` | ✅ | (binary) | (binary) | (perl) |
134
+ | **Diff mode (`--since`) + baselines** | ✅ | ❌ | ❌ | ❌ |
135
+ | **CI gate + regression ratchet** | ✅ | | | |
136
+ | **Config file** (`[tool.repoglance]`) | ✅ | ✅ | ❌ | ❌ |
117
137
 
118
138
  ## Share it: badges & reports
119
139
 
@@ -206,6 +226,27 @@ repoglance --badge-json .repoglance-badge.json # commit this file
206
226
  repoglance --md # paste into a PR, wiki, or Slack
207
227
  ```
208
228
 
229
+ ### Configuration file
230
+
231
+ Set defaults once via `.repoglance.toml` or a `[tool.repoglance]` table in
232
+ `pyproject.toml` (CLI flags always win):
233
+
234
+ ```toml
235
+ [tool.repoglance]
236
+ exclude = ["**/*_pb2.py", "vendor/**"]
237
+ max_complexity = 25
238
+ fail_under = 70
239
+ ```
240
+
241
+ ### Docker & GitLab
242
+
243
+ ```bash
244
+ docker run --rm -v "$PWD:/repo" repoglance /repo
245
+ ```
246
+
247
+ A ready-to-copy GitLab CI job lives in
248
+ [`integrations/gitlab-ci.yml`](integrations/gitlab-ci.yml).
249
+
209
250
  ## Design goals
210
251
 
211
252
  - **Fast** — a single pass, no external services.
@@ -0,0 +1,27 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a vulnerability
4
+
5
+ If you find a security issue in repoglance, please report it privately:
6
+
7
+ - Open a [GitHub security advisory](https://github.com/SRJ-ai/repoglance/security/advisories/new), **or**
8
+ - Email the maintainers with the details.
9
+
10
+ Please do **not** open a public issue for security problems.
11
+
12
+ We aim to acknowledge reports within 3 business days and to ship a fix or
13
+ mitigation as quickly as the severity warrants.
14
+
15
+ ## Scope notes
16
+
17
+ repoglance is a local, read-only analysis tool: it does not make network
18
+ requests, send telemetry, or write outside the paths you explicitly pass for
19
+ report/badge output. It does shell out to `git` for repository metadata. The
20
+ most relevant considerations are therefore:
21
+
22
+ - Handling of untrusted repository contents (file parsing, path handling).
23
+ - The `git` subprocess invocations in `gitinfo.py` and `scanner.py`.
24
+
25
+ ## Supported versions
26
+
27
+ The latest released version on PyPI receives security fixes.
@@ -21,6 +21,14 @@ inputs:
21
21
  description: "Fail the job if any function exceeds this cyclomatic complexity. Empty to disable."
22
22
  required: false
23
23
  default: ""
24
+ sarif:
25
+ description: "Generate SARIF and upload it to GitHub code scanning (requires security-events: write)."
26
+ required: false
27
+ default: "false"
28
+ diff-base:
29
+ description: "Only analyze files changed since this git ref (e.g. origin/main). Empty = whole repo."
30
+ required: false
31
+ default: ""
24
32
  github-token:
25
33
  description: "Token used to post the PR comment."
26
34
  required: false
@@ -41,9 +49,22 @@ runs:
41
49
  - name: Job summary + Markdown report
42
50
  shell: bash
43
51
  run: |
44
- repoglance "${{ inputs.path }}" --md > "$RUNNER_TEMP/repoglance.md"
52
+ since=""
53
+ [ -n "${{ inputs.diff-base }}" ] && since="--since ${{ inputs.diff-base }}"
54
+ repoglance "${{ inputs.path }}" $since --md > "$RUNNER_TEMP/repoglance.md"
45
55
  cat "$RUNNER_TEMP/repoglance.md" >> "$GITHUB_STEP_SUMMARY"
46
56
 
57
+ - name: Generate SARIF
58
+ if: ${{ inputs.sarif == 'true' }}
59
+ shell: bash
60
+ run: repoglance "${{ inputs.path }}" --sarif > "$RUNNER_TEMP/repoglance.sarif"
61
+
62
+ - name: Upload SARIF
63
+ if: ${{ inputs.sarif == 'true' }}
64
+ uses: github/codeql-action/upload-sarif@v3
65
+ with:
66
+ sarif_file: ${{ runner.temp }}/repoglance.sarif
67
+
47
68
  - name: Comment on PR
48
69
  if: ${{ inputs.comment == 'true' && github.event_name == 'pull_request' }}
49
70
  shell: bash
@@ -1,19 +1,19 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="200" height="20" role="img" aria-label="repoglance: 1.6k loc • Python">
2
- <title>repoglance: 1.6k loc • Python</title>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="202" height="20" role="img" aria-label="repoglance: 2.3k loc • Python">
2
+ <title>repoglance: 2.3k loc • Python</title>
3
3
  <linearGradient id="s" x2="0" y2="100%">
4
4
  <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
5
5
  <stop offset="1" stop-opacity=".1"/>
6
6
  </linearGradient>
7
- <clipPath id="r"><rect width="200" height="20" rx="3" fill="#fff"/></clipPath>
7
+ <clipPath id="r"><rect width="202" height="20" rx="3" fill="#fff"/></clipPath>
8
8
  <g clip-path="url(#r)">
9
9
  <rect width="84" height="20" fill="#555"/>
10
- <rect x="84" width="117" height="20" fill="#3572A5"/>
11
- <rect width="200" height="20" fill="url(#s)"/>
10
+ <rect x="84" width="118" height="20" fill="#3572A5"/>
11
+ <rect width="202" height="20" fill="url(#s)"/>
12
12
  </g>
13
13
  <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="110" text-rendering="geometricPrecision">
14
14
  <text aria-hidden="true" x="418" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="635">repoglance</text>
15
15
  <text x="418" y="140" transform="scale(.1)" textLength="635">repoglance</text>
16
- <text aria-hidden="true" x="1420" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="970">1.6k loc • Python</text>
17
- <text x="1420" y="140" transform="scale(.1)" textLength="970">1.6k loc • Python</text>
16
+ <text aria-hidden="true" x="1425" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="980">2.3k loc • Python</text>
17
+ <text x="1425" y="140" transform="scale(.1)" textLength="980">2.3k loc • Python</text>
18
18
  </g>
19
19
  </svg>