dark-matter-cli 0.1.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.
@@ -0,0 +1,59 @@
1
+ name: 🐛 Bug Report
2
+ description: Report anomalous pipeline behavior or incorrect bloat mass calculations.
3
+ title: "[BUG]: <brief description>"
4
+ labels: ["bug"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for helping map the unseen mass. Please provide as much telemetry as possible so we can accurately reproduce the anomaly in the local DAG.
10
+ - type: textarea
11
+ id: description
12
+ attributes:
13
+ label: Anomaly Description
14
+ description: A clear and concise description of the pipeline failure or mathematical error.
15
+ placeholder: When computing the transitive in-degree map, dark-matter encounters a KeyError...
16
+ validations:
17
+ required: true
18
+ - type: textarea
19
+ id: reproduction
20
+ attributes:
21
+ label: Reproduction Vector
22
+ description: The exact CLI invocation or state required to reproduce the behavior.
23
+ placeholder: |
24
+ 1. Have package `X` installed via Homebrew
25
+ 2. Execute `dark-matter --sort recursive --standard`
26
+ 3. Observe pipeline termination
27
+ validations:
28
+ required: true
29
+ - type: textarea
30
+ id: expected
31
+ attributes:
32
+ label: Expected Behavior
33
+ description: What did you mathematically or programmatically expect the pipeline to output?
34
+ validations:
35
+ required: true
36
+ - type: textarea
37
+ id: logs
38
+ attributes:
39
+ label: Traceback / Output Logs
40
+ description: Paste any relevant stderr tracebacks or verbose CLI output.
41
+ render: python
42
+ - type: input
43
+ id: version
44
+ attributes:
45
+ label: Dark Matter Version
46
+ description: Output of `dark-matter --version`
47
+ placeholder: "0.1.0"
48
+ validations:
49
+ required: true
50
+ - type: dropdown
51
+ id: os
52
+ attributes:
53
+ label: Operating System / Architecture
54
+ options:
55
+ - macOS (Apple Silicon / ARM64)
56
+ - macOS (Intel / x86_64)
57
+ - Linux (POSIX)
58
+ validations:
59
+ required: true
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Theoretical or Mathematical Inquiries
4
+ url: https://github.com/jacksonfergusondev/dark-matter/issues
5
+ about: Unsure how the Fractional Attribution Model distributes package mass? Open a general issue.
@@ -0,0 +1,29 @@
1
+ name: 🚀 Feature Request
2
+ description: Propose a new metric, attribution model, or pipeline enhancement.
3
+ title: "[FEAT]: <brief description>"
4
+ labels: ["enhancement"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Have an idea to improve the resolution of the cosmological storage mapping? Detail the theoretical model or structural enhancement below.
10
+ - type: textarea
11
+ id: problem
12
+ attributes:
13
+ label: The Problem
14
+ description: Is this request addressing a specific limitation or graph-ignorance in the current pipeline?
15
+ placeholder: The current fractional model does not account for...
16
+ validations:
17
+ required: true
18
+ - type: textarea
19
+ id: solution
20
+ attributes:
21
+ label: Proposed Solution
22
+ description: Detail the programmatic implementation or mathematical algorithm you'd like to see added.
23
+ validations:
24
+ required: true
25
+ - type: textarea
26
+ id: alternatives
27
+ attributes:
28
+ label: Alternatives Considered
29
+ description: Are there other algorithms, heuristics, or external tooling that could achieve a similar result?
@@ -0,0 +1,60 @@
1
+ {
2
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
+ "extends": [
4
+ "config:best-practices",
5
+ ":semanticCommits",
6
+ ":prHourlyLimit2"
7
+ ],
8
+ "ignorePaths": [
9
+ "docs/**",
10
+ "scripts/**",
11
+ "src/**",
12
+ "tests/**"
13
+ ],
14
+ "schedule": [
15
+ "before 4am on monday"
16
+ ],
17
+ "internalChecksFilter": "strict",
18
+ "rebaseWhen": "conflicted",
19
+ "labels": [
20
+ "dependencies",
21
+ "chore"
22
+ ],
23
+ "vulnerabilityAlerts": {
24
+ "schedule": [
25
+ "at any time"
26
+ ]
27
+ },
28
+ "packageRules": [
29
+ {
30
+ "description": "Require a package to be 2 weeks old before updating, but exclude vulnerability remediation from this wait.",
31
+ "matchUpdateTypes": [
32
+ "major",
33
+ "minor",
34
+ "patch",
35
+ "pin",
36
+ "digest"
37
+ ],
38
+ "minimumReleaseAge": "2 weeks"
39
+ },
40
+ {
41
+ "description": "Group all python dev-dependencies (ruff, mypy, pytest) into one PR and automerge them.",
42
+ "matchFileNames": [
43
+ "pyproject.toml"
44
+ ],
45
+ "matchDepTypes": [
46
+ "dependency-groups"
47
+ ],
48
+ "groupName": "python-dev-tools",
49
+ "automerge": true
50
+ },
51
+ {
52
+ "description": "Group GitHub Actions updates and automerge them.",
53
+ "matchManagers": [
54
+ "github-actions"
55
+ ],
56
+ "groupName": "github-actions",
57
+ "automerge": true
58
+ }
59
+ ]
60
+ }
@@ -0,0 +1,65 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ "main" ]
6
+ pull_request:
7
+ branches: [ "main" ]
8
+
9
+ jobs:
10
+ lint:
11
+ name: Lint & Type Check
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
16
+
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
19
+ with:
20
+ enable-cache: true
21
+ python-version: "3.12"
22
+
23
+ - name: Install dependencies
24
+ run: uv sync --only-group ci --locked
25
+
26
+ - name: Run Ruff Linter
27
+ run: uv run ruff check --output-format=github .
28
+
29
+ - name: Run Ruff Formatter
30
+ run: uv run ruff format --check --output-format=github .
31
+
32
+ - name: Lint Markdown with rumdl
33
+ run: uv run rumdl check --output-format github .
34
+
35
+ - name: Check Markdown formatting with rumdl
36
+ run: uv run rumdl fmt --check --output-format github .
37
+
38
+ - name: Type check with Mypy
39
+ run: uv run mypy .
40
+
41
+ test:
42
+ name: Test on ${{ matrix.os }} / Python ${{ matrix.python-version }}
43
+ runs-on: ${{ matrix.os }}
44
+ strategy:
45
+ fail-fast: false
46
+ matrix:
47
+ os: [ubuntu-latest, macos-latest]
48
+ python-version: ["3.12", "3.13", "3.14"]
49
+
50
+ steps:
51
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
52
+
53
+ - name: Install uv
54
+ uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
55
+ with:
56
+ enable-cache: true
57
+ python-version: ${{ matrix.python-version }}
58
+
59
+ - name: Install dependencies
60
+ run: |
61
+ uv sync --only-group ci --locked
62
+ uv pip install pytest-github-actions-annotate-failures
63
+
64
+ - name: Run tests
65
+ run: uv run pytest
@@ -0,0 +1,40 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+
8
+ jobs:
9
+ build-n-publish:
10
+ name: Build and publish to PyPI
11
+ runs-on: ubuntu-latest
12
+ environment: release
13
+ permissions:
14
+ contents: read
15
+ id-token: write
16
+
17
+ steps:
18
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
19
+
20
+ - name: Install uv
21
+ uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
22
+ with:
23
+ python-version: "3.14"
24
+
25
+ - name: Build distribution
26
+ run: uv build
27
+
28
+ - name: Publish to PyPI
29
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
30
+
31
+ sync-homebrew:
32
+ name: Delegate Homebrew Update
33
+ needs: build-n-publish
34
+ uses: JacksonFergusonDev/ci-cd-tooling/.github/workflows/update-homebrew.yml@9300b4398eaedd7f3b369614433b38680e42ef02 # main
35
+ with:
36
+ tag: ${{ github.ref_name }}
37
+ package_name: "protostar"
38
+ formula_path: "Formula/protostar.rb"
39
+ secrets:
40
+ TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}
@@ -0,0 +1,16 @@
1
+ *~
2
+ .DS_Store
3
+ .coverage
4
+ .direnv/
5
+ .env
6
+ .envrc.local
7
+ .idea/
8
+ .mypy_cache/
9
+ .pytest_cache/
10
+ .ruff_cache/
11
+ .venv/
12
+ .vscode/
13
+ Thumbs.db
14
+ __pycache__/
15
+ coverage.xml
16
+ htmlcov/
@@ -0,0 +1,108 @@
1
+ default_install_hook_types:
2
+ - pre-commit
3
+ - commit-msg
4
+ - pre-push
5
+
6
+ default_stages:
7
+ - pre-commit
8
+
9
+ fail_fast: true
10
+
11
+ repos:
12
+ # Generic hooks (configured to IGNORE Python)
13
+ - repo: builtin
14
+ hooks:
15
+ - id: check-added-large-files
16
+ - id: check-merge-conflict
17
+ - id: check-case-conflict
18
+ - id: check-symlinks
19
+ - id: check-executables-have-shebangs
20
+ - id: trailing-whitespace
21
+ exclude: \.py$
22
+ - id: end-of-file-fixer
23
+ exclude: \.py$|\.gitkeep$
24
+ - id: check-yaml
25
+ - id: check-json
26
+ - id: check-toml
27
+
28
+ # Local Python + Markdown Toolchain (Managed via uv.lock)
29
+ - repo: local
30
+ hooks:
31
+ - id: uv-lock-check
32
+ name: uv lock check
33
+ entry: uv lock --check
34
+ language: system
35
+ pass_filenames: false
36
+ files: ^(pyproject\.toml|uv\.lock)$
37
+
38
+ - id: ruff-check
39
+ name: ruff check
40
+ entry: uv run ruff check --fix
41
+ language: system
42
+ types: [python]
43
+ exclude: ^docs/
44
+ require_serial: true
45
+
46
+ - id: ruff-format
47
+ name: ruff format
48
+ entry: uv run ruff format
49
+ language: system
50
+ types: [python]
51
+ exclude: ^docs/
52
+ require_serial: true
53
+
54
+ - id: mypy
55
+ name: mypy
56
+ entry: uv run mypy
57
+ language: system
58
+ types: [python]
59
+ exclude: ^docs/
60
+ require_serial: true
61
+
62
+ - id: rumdl-check
63
+ name: rumdl check
64
+ entry: uv run rumdl check --fix
65
+ language: system
66
+ types: [markdown]
67
+ require_serial: true
68
+
69
+ - id: rumdl-fmt
70
+ name: rumdl fmt
71
+ entry: uv run rumdl fmt
72
+ language: system
73
+ types: [markdown]
74
+ require_serial: true
75
+
76
+ - id: pytest-unit
77
+ name: pytest unit tests
78
+ entry: uv run pytest
79
+ language: system
80
+ pass_filenames: false
81
+ stages: [pre-push]
82
+
83
+ # Check for accidental commits of secrets
84
+ - repo: https://github.com/gitleaks/gitleaks
85
+ rev: v8.30.1
86
+ hooks:
87
+ - id: gitleaks
88
+
89
+ # Commit message validation
90
+ - repo: https://github.com/Goldziher/gitfluff
91
+ rev: v0.8.0
92
+ hooks:
93
+ - id: gitfluff-lint
94
+ args: [--write]
95
+ stages: [commit-msg]
96
+
97
+ # Renovate config validation
98
+ - repo: https://github.com/renovatebot/pre-commit-hooks
99
+ rev: 44.24.3
100
+ hooks:
101
+ - id: renovate-config-validator
102
+ files: '.github/renovate.json'
103
+
104
+ # GitHub Actions workflow validation
105
+ - repo: https://github.com/rhysd/actionlint
106
+ rev: v1.7.12
107
+ hooks:
108
+ - id: actionlint
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,33 @@
1
+ # Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, religion, or sexual identity
10
+ and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ - Demonstrating empathy and kindness toward other people
21
+ - Being respectful of differing opinions, viewpoints, and experiences
22
+ - Giving and gracefully accepting constructive feedback
23
+ - Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ - Focusing on what is best not just for us as individuals, but for the
26
+ overall community
27
+
28
+ ## Enforcement
29
+
30
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
31
+ reported by contacting the project maintainer at **<jackson.ferguson0@gmail.com>**.
32
+ All complaints will be reviewed and
33
+ investigated promptly and fairly.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jackson Ferguson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,200 @@
1
+ Metadata-Version: 2.5
2
+ Name: dark-matter-cli
3
+ Version: 0.1.0
4
+ Summary: A dependency-graph-aware storage profiler for Homebrew.
5
+ Project-URL: Repository, https://github.com/jacksonfergusondev/dark-matter
6
+ Project-URL: Issues, https://github.com/jacksonfergusondev/dark-matter/issues
7
+ Project-URL: PyPI, https://pypi.org/project/dark-matter-cli/
8
+ Author-email: Jackson Ferguson <jackson.ferguson0@gmail.com>
9
+ License: MIT License
10
+
11
+ Copyright (c) 2026 Jackson Ferguson
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
30
+ License-File: LICENSE
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Operating System :: MacOS
33
+ Classifier: Operating System :: POSIX :: Linux
34
+ Classifier: Programming Language :: Python :: 3
35
+ Classifier: Programming Language :: Python :: 3.12
36
+ Classifier: Programming Language :: Python :: 3.13
37
+ Classifier: Programming Language :: Python :: 3.14
38
+ Requires-Python: >=3.12
39
+ Requires-Dist: pandas>=3.0.3
40
+ Requires-Dist: requests>=2.34.0
41
+ Requires-Dist: rich>=15.0.0
42
+ Requires-Dist: typer>=0.25.1
43
+ Description-Content-Type: text/markdown
44
+
45
+ <!-- rumdl-disable-file first-line-heading -->
46
+ <div align="center">
47
+
48
+ # Dark Matter
49
+
50
+ **A dependency-graph-aware storage profiler for Homebrew.**
51
+
52
+ [![CI](https://img.shields.io/github/actions/workflow/status/JacksonFergusonDev/dark-matter/ci.yml?style=flat-square&color=white&labelColor=0A0A0A&label=CI)](https://github.com/JacksonFergusonDev/dark-matter/actions/workflows/ci.yml)
53
+ [![Python](https://img.shields.io/badge/python-3.12+-white?style=flat-square&labelColor=0A0A0A)](https://www.python.org/downloads/)
54
+ [![Ruff](https://img.shields.io/badge/style-ruff-white?style=flat-square&labelColor=0A0A0A)](https://github.com/astral-sh/ruff)
55
+ [![Mypy](https://img.shields.io/badge/mypy-checked-white?style=flat-square&labelColor=0A0A0A)](https://mypy-lang.org/)
56
+ [![prek](https://img.shields.io/badge/prek-enabled-white?style=flat-square&labelColor=black)](https://github.com/j178/prek)
57
+ [![License](https://img.shields.io/badge/license-MIT-white?style=flat-square&labelColor=0A0A0A)](LICENSE)
58
+
59
+ </div>
60
+
61
+ ## Why
62
+
63
+ Homebrew flattens every dependency into a single `Cellar` directory. Tools like `du` or `ncdu` can tell you a formula takes up 500 MB, but they have no concept of *why* — whether that mass belongs to the formula itself or to a shared runtime pulled in by five other packages you installed for unrelated reasons.
64
+
65
+ Dark Matter reconstructs the dependency graph Homebrew already knows about and uses it to answer a more useful question: for each package you explicitly installed, how much disk space does it actually cost you, once shared dependencies are fairly split across everything that depends on them?
66
+
67
+ ## How it works
68
+
69
+ Dark Matter parses Homebrew's own JSON metadata (via `brew info --json=v2` or its local API cache), rebuilds the dependency DAG, and walks it to compute two figures per package:
70
+
71
+ - **Core size** — the package's own on-disk footprint (or, in theoretical mode, its compressed bottle archive).
72
+ - **Weighted recursive size** — the core size plus a *fair share* of every transitive dependency, where each shared dependency's cost is divided evenly across all the packages that depend on it.
73
+
74
+ The ratio between the two — the **Bloat Ratio** — is the headline number. A low ratio means a package is mostly self-contained; a high ratio means most of its footprint belongs to shared infrastructure it happens to require.
75
+
76
+ ## Features
77
+
78
+ - **Comprehensive analysis suite**
79
+ - `analyze` — measures what's actually on disk, using `brew info --json=v2 --installed` and direct filesystem traversal (`os.scandir`) for exact byte counts.
80
+ - `leaderboard` — a theoretical mode that ranks Homebrew's *entire* formula and cask catalog from the local API cache, without requiring anything to be installed.
81
+ - `inspect` & `compare` — targeted O(1) theoretical resolution for individual or grouped packages without resolving the entire ecosystem payload.
82
+ - `explain` — breaks down a target package's bloat by attributing fractional byte costs to each of its transitive dependencies.
83
+ - `export` — streams the underlying DataFrames to CSV or JSON for integration into external data pipelines.
84
+ - **Fractional Attribution Model** — shared dependencies (`openssl`, `python`, etc.) are divided proportionally across all parent packages instead of being double-counted, giving an honest per-package cost.
85
+ - **Daemon-free** — no background indexing, no persistent database. Every run is a fresh, on-demand computation.
86
+ - **Typed and tested** — fully type-annotated (strict `mypy`), linted with `ruff`, and covered by a `pytest` suite exercising the DAG traversal, fractional math, and network resolution logic. CI runs the full suite on macOS and Ubuntu across Python 3.12 and 3.14.
87
+
88
+ ## A note on theoretical measurements
89
+
90
+ `leaderboard`, `inspect`, `compare`, and `explain` rely on `Content-Length` headers from `ghcr.io` blob storage, which report *compressed* archive size, not the size a package occupies once unpacked to disk. The absolute numbers they report will therefore run lower than `analyze`'s physical measurements.
91
+
92
+ The Bloat Ratio, however, stays meaningful. Since most bottles compress with similar algorithms (gzip or zstd), the compression factor $c$ appears in both the numerator and denominator and cancels out:
93
+
94
+ $$R \approx \frac{c \cdot m_{recursive}}{c \cdot m_{core}} \approx \frac{m_{recursive}}{m_{core}}$$
95
+
96
+ So while theoretical modes shouldn't be read as precise disk-space forecasts, they are a reliable way to evaluate relative bloat without installing anything.
97
+
98
+ ## Installation
99
+
100
+ ```bash
101
+ git clone https://github.com/jacksonfergusondev/dark-matter.git
102
+ cd dark-matter
103
+ uv tool install --editable .
104
+ ```
105
+
106
+ ## Usage
107
+
108
+ ```bash
109
+ # Analyze what's actually installed
110
+ dark-matter analyze
111
+
112
+ # Rank the entire Homebrew catalog by theoretical bloat
113
+ dark-matter leaderboard
114
+
115
+ # Evaluate a specific formula instantly
116
+ dark-matter inspect uv
117
+
118
+ # Break down the dependency bloat of a specific package
119
+ dark-matter explain uv
120
+
121
+ # Compare multiple packages side-by-side
122
+ dark-matter compare uv poetry pdm
123
+
124
+ # Export the entire graph to JSON for external analysis
125
+ dark-matter export --format json > homebrew_bloat.json
126
+ ```
127
+
128
+ All commands accept the global `--verbose` / `-v` flag for debug logging, and `--version` to print the installed version.
129
+
130
+ ### `analyze`
131
+
132
+ | Flag | Default | Description |
133
+ | --- | --- | --- |
134
+ | `--sort` / `-s` | `ratio` | Sort by `ratio`, `core`, or `recursive` |
135
+ | `--top` / `-n` | `20` | Number of packages to display |
136
+ | `--fractional` / `--standard` | `--fractional` | Toggle the Fractional Attribution Model |
137
+
138
+ ### `leaderboard`
139
+
140
+ | Flag | Default | Description |
141
+ | --- | --- | --- |
142
+ | `--sort` / `-s` | `ratio` | Sort by `ratio`, `core`, or `recursive` |
143
+ | `--top` / `-n` | `20` | Number of packages to display |
144
+ | `--arch` / `-a` | `arm64_tahoe` | Target bottle architecture |
145
+
146
+ ### `inspect`
147
+
148
+ | Argument/Flag | Default | Description |
149
+ | --- | --- | --- |
150
+ | `[PACKAGE]` | **Required** | The target package to analyze |
151
+ | `--source` / `-s` | `installed` | Data source to compute: `installed` or `catalog` |
152
+ | `--arch` / `-a` | `arm64_tahoe` | Target bottle architecture |
153
+
154
+ ### `compare`
155
+
156
+ | Argument/Flag | Default | Description |
157
+ | --- | --- | --- |
158
+ | `[PACKAGES]...` | **Required** | A space-separated list of packages to compare |
159
+ | `--sort` / `-s` | `ratio` | Sort by `ratio`, `core`, or `recursive` |
160
+ | `--source` / `-s` | `installed` | Data source to compute: `installed` or `catalog` |
161
+ | `--arch` / `-a` | `arm64_tahoe` | Target bottle architecture |
162
+
163
+ ### `explain`
164
+
165
+ | Argument/Flag | Default | Description |
166
+ | --- | --- | --- |
167
+ | `[PACKAGE]` | **Required** | The specific package to analyze |
168
+ | `--source` / `-s` | `installed` | Data source to compute: `installed` or `catalog` |
169
+ | `--arch` / `-a` | `arm64_tahoe` | Target bottle architecture |
170
+
171
+ ### `export`
172
+
173
+ | Flag | Default | Description |
174
+ | --- | --- | --- |
175
+ | `--source` / `-s` | `installed` | Data source to compute: `installed` or `catalog` |
176
+ | `--format` / `-f` | `csv` | Output format: `csv` or `json` |
177
+ | `--arch` / `-a` | `arm64_tahoe` | Target bottle architecture (for `catalog` source) |
178
+
179
+ ## Development
180
+
181
+ The project uses [`just`](https://github.com/casey/just) to wrap common tasks:
182
+
183
+ ```bash
184
+ just format # ruff format + fix
185
+ just lint # ruff + rumdl
186
+ just typecheck # mypy
187
+ just test # pytest
188
+ just test-cov # pytest with coverage report
189
+ just ci # the full pipeline CI runs, locally
190
+ ```
191
+
192
+ ## 📧 Contact
193
+
194
+ [![GitHub](https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white)](https://github.com/JacksonFergusonDev)
195
+ [![LinkedIn](https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/jackson--ferguson/)
196
+ [![Email](https://img.shields.io/badge/Email-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:jackson.ferguson0@gmail.com)
197
+
198
+ ## 📄 License
199
+
200
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.