slopguard-cli 0.1.0__tar.gz → 0.1.1__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 (51) hide show
  1. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/.gitignore +11 -0
  2. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/PKG-INFO +3 -3
  3. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/README.md +2 -1
  4. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/pyproject.toml +1 -1
  5. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/__init__.py +1 -1
  6. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/test_cli.py +2 -2
  7. slopguard_cli-0.1.0/.github/workflows/ci.yml +0 -52
  8. slopguard_cli-0.1.0/.github/workflows/release.yml +0 -68
  9. slopguard_cli-0.1.0/.github/workflows/slopguard.yml.example +0 -35
  10. slopguard_cli-0.1.0/CONTRIBUTING.md +0 -30
  11. slopguard_cli-0.1.0/LICENSE +0 -21
  12. slopguard_cli-0.1.0/docs/ci-integration.md +0 -106
  13. slopguard_cli-0.1.0/docs/detection.md +0 -77
  14. slopguard_cli-0.1.0/docs/usage.md +0 -103
  15. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/.ruff.toml +0 -0
  16. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/Makefile +0 -0
  17. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/scripts/generate_seed_data.py +0 -0
  18. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/__main__.py +0 -0
  19. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/cli.py +0 -0
  20. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/config.py +0 -0
  21. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/data/__init__.py +0 -0
  22. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/data/hallucinations_seed.json +0 -0
  23. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/data/popular_packages.json +0 -0
  24. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/models.py +0 -0
  25. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/parsers/__init__.py +0 -0
  26. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/parsers/base.py +0 -0
  27. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/parsers/npm.py +0 -0
  28. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/parsers/python.py +0 -0
  29. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/registry/__init__.py +0 -0
  30. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/registry/base.py +0 -0
  31. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/registry/npm.py +0 -0
  32. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/registry/pypi.py +0 -0
  33. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/report/__init__.py +0 -0
  34. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/report/json.py +0 -0
  35. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/report/terminal.py +0 -0
  36. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/scoring/__init__.py +0 -0
  37. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/scoring/engine.py +0 -0
  38. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/scoring/signals.py +0 -0
  39. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/slopguard/update.py +0 -0
  40. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/__init__.py +0 -0
  41. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/conftest.py +0 -0
  42. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/fixtures/.slopguard.yaml +0 -0
  43. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/fixtures/package.json +0 -0
  44. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/fixtures/pyproject.toml +0 -0
  45. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/fixtures/requirements.txt +0 -0
  46. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/test_misc.py +0 -0
  47. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/test_parsers_npm.py +0 -0
  48. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/test_parsers_python.py +0 -0
  49. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/test_registry_npm.py +0 -0
  50. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/test_registry_pypi.py +0 -0
  51. {slopguard_cli-0.1.0 → slopguard_cli-0.1.1}/tests/test_scoring_engine.py +0 -0
@@ -41,3 +41,14 @@ Thumbs.db
41
41
 
42
42
  # Local scan artifacts
43
43
  slopguard-report.json
44
+
45
+ # Node / Next.js (Phase A onwards)
46
+ node_modules/
47
+ .next/
48
+ out/
49
+ .turbo/
50
+
51
+ # Local secrets — never commit. Use Doppler / 1Password / Fly.io secrets.
52
+ .env
53
+ .env.*
54
+ !.env.example
@@ -1,13 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slopguard-cli
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Defend developers and AI coding agents against slopsquatting (hallucinated package names).
5
5
  Project-URL: Homepage, https://github.com/hariomunknownslab/slopguard
6
6
  Project-URL: Repository, https://github.com/hariomunknownslab/slopguard
7
7
  Project-URL: Issues, https://github.com/hariomunknownslab/slopguard/issues
8
8
  Author-email: SlopGuard <contact@unknownslab.com>
9
9
  License: MIT
10
- License-File: LICENSE
11
10
  Keywords: ai,llm,package-hallucination,security,slopsquatting,supply-chain
12
11
  Classifier: Development Status :: 3 - Alpha
13
12
  Classifier: Intended Audience :: Developers
@@ -40,7 +39,8 @@ Description-Content-Type: text/markdown
40
39
  # SlopGuard
41
40
 
42
41
  [![CI](https://github.com/hariomunknownslab/slopguard/actions/workflows/ci.yml/badge.svg)](https://github.com/hariomunknownslab/slopguard/actions/workflows/ci.yml)
43
- [![PyPI](https://img.shields.io/pypi/v/slopguard.svg)](https://pypi.org/project/slopguard/)
42
+ [![PyPI](https://img.shields.io/pypi/v/slopguard-cli.svg)](https://pypi.org/project/slopguard-cli/)
43
+ [![Python](https://img.shields.io/pypi/pyversions/slopguard-cli.svg)](https://pypi.org/project/slopguard-cli/)
44
44
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
45
45
 
46
46
  **Slopsquatting** is what happens when an LLM hallucinates a plausible-sounding
@@ -1,7 +1,8 @@
1
1
  # SlopGuard
2
2
 
3
3
  [![CI](https://github.com/hariomunknownslab/slopguard/actions/workflows/ci.yml/badge.svg)](https://github.com/hariomunknownslab/slopguard/actions/workflows/ci.yml)
4
- [![PyPI](https://img.shields.io/pypi/v/slopguard.svg)](https://pypi.org/project/slopguard/)
4
+ [![PyPI](https://img.shields.io/pypi/v/slopguard-cli.svg)](https://pypi.org/project/slopguard-cli/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/slopguard-cli.svg)](https://pypi.org/project/slopguard-cli/)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
7
 
7
8
  **Slopsquatting** is what happens when an LLM hallucinates a plausible-sounding
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "slopguard-cli"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "Defend developers and AI coding agents against slopsquatting (hallucinated package names)."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -2,6 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "0.1.0"
5
+ __version__ = "0.1.1"
6
6
 
7
7
  __all__ = ["__version__"]
@@ -107,7 +107,7 @@ def runner() -> CliRunner:
107
107
  def test_version_subcommand(runner: CliRunner) -> None:
108
108
  result = runner.invoke(app, ["version"])
109
109
  assert result.exit_code == 0
110
- assert result.stdout.strip() == "0.1.0"
110
+ assert result.stdout.strip() == "0.1.1"
111
111
 
112
112
 
113
113
  def test_scan_fixtures_no_network_terminal(runner: CliRunner, fixtures_dir: Path) -> None:
@@ -183,4 +183,4 @@ def test_module_main_runs() -> None:
183
183
  check=False,
184
184
  )
185
185
  assert result.returncode == 0
186
- assert result.stdout.strip() == "0.1.0"
186
+ assert result.stdout.strip() == "0.1.1"
@@ -1,52 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- pull_request:
5
- push:
6
- branches: [main]
7
-
8
- jobs:
9
- test:
10
- runs-on: ubuntu-latest
11
- strategy:
12
- fail-fast: false
13
- matrix:
14
- python-version: ["3.11", "3.12"]
15
- steps:
16
- - uses: actions/checkout@v4
17
- - uses: actions/setup-python@v5
18
- with:
19
- python-version: ${{ matrix.python-version }}
20
- cache: pip
21
- - name: Install
22
- run: |
23
- python -m pip install --upgrade pip
24
- pip install -e ".[dev]"
25
- - name: Lint
26
- run: |
27
- ruff check slopguard/ tests/
28
- ruff format --check slopguard/ tests/
29
- - name: Type check
30
- run: mypy --strict slopguard/
31
- - name: Test
32
- run: pytest -q --cov=slopguard --cov-report=term --cov-fail-under=85
33
- - name: Build wheel
34
- if: matrix.python-version == '3.11'
35
- run: |
36
- pip install build
37
- python -m build
38
- - name: Smoke-test wheel install
39
- if: matrix.python-version == '3.11'
40
- run: |
41
- python -m venv /tmp/wheel-venv
42
- /tmp/wheel-venv/bin/pip install dist/*.whl
43
- /tmp/wheel-venv/bin/slopguard version
44
- # Fixtures contain known hallucinations on purpose, so scan exits 1.
45
- # Assert that, then validate the JSON payload.
46
- set +e
47
- /tmp/wheel-venv/bin/slopguard scan tests/fixtures --no-network --format json --output /tmp/report.json
48
- rc=$?
49
- set -e
50
- test "$rc" = "1"
51
- test "$(jq -r .slopguard_version /tmp/report.json)" = "0.1.0"
52
- test "$(jq -r .summary.hallucinated /tmp/report.json)" -ge 1
@@ -1,68 +0,0 @@
1
- name: Release to PyPI
2
-
3
- # Triggered when a GitHub release is published, or manually via the Actions UI.
4
- # The first run will register the project on PyPI under whoever owns the
5
- # trusted publisher configuration on the PyPI side.
6
- #
7
- # Setup once on PyPI: https://pypi.org/manage/account/publishing/ → "Add a new
8
- # pending publisher" with:
9
- # PyPI Project Name: slopguard
10
- # Owner: hariomunknownslab
11
- # Repository name: slopguard
12
- # Workflow name: release.yml
13
- # Environment name: (leave blank)
14
- # After the first successful run, PyPI promotes the pending publisher to a real
15
- # project-scoped trusted publisher; no token is ever stored.
16
-
17
- on:
18
- release:
19
- types: [published]
20
- workflow_dispatch:
21
- inputs:
22
- ref:
23
- description: "Git ref to publish (tag, branch, or SHA). Defaults to the workflow's ref."
24
- required: false
25
- default: ""
26
-
27
- permissions:
28
- contents: read
29
-
30
- jobs:
31
- build:
32
- name: Build sdist + wheel
33
- runs-on: ubuntu-latest
34
- steps:
35
- - uses: actions/checkout@v4
36
- with:
37
- ref: ${{ inputs.ref || github.ref }}
38
- - uses: actions/setup-python@v5
39
- with:
40
- python-version: "3.11"
41
- - name: Install build
42
- run: python -m pip install --upgrade build
43
- - name: Build
44
- run: python -m build
45
- - name: Verify metadata
46
- run: |
47
- python -m pip install twine
48
- python -m twine check dist/*
49
- - name: Upload artifact
50
- uses: actions/upload-artifact@v4
51
- with:
52
- name: pypi-dists
53
- path: dist/
54
-
55
- publish:
56
- name: Publish to PyPI
57
- needs: build
58
- runs-on: ubuntu-latest
59
- permissions:
60
- id-token: write # required for OIDC trusted publishing
61
- steps:
62
- - name: Download artifact
63
- uses: actions/download-artifact@v4
64
- with:
65
- name: pypi-dists
66
- path: dist/
67
- - name: Publish
68
- uses: pypa/gh-action-pypi-publish@release/v1
@@ -1,35 +0,0 @@
1
- # Copy this file into your own repository as `.github/workflows/slopguard.yml`.
2
- #
3
- # It installs SlopGuard, scans the repository on every pull request and push to
4
- # main, and uploads the JSON report as a build artifact. The job fails the
5
- # build whenever SlopGuard exits non-zero.
6
-
7
- name: SlopGuard
8
-
9
- on:
10
- pull_request:
11
- push:
12
- branches: [main]
13
-
14
- jobs:
15
- slopguard:
16
- runs-on: ubuntu-latest
17
- steps:
18
- - uses: actions/checkout@v4
19
-
20
- - uses: actions/setup-python@v5
21
- with:
22
- python-version: "3.11"
23
-
24
- - name: Install SlopGuard
25
- run: pip install slopguard-cli
26
-
27
- - name: Scan
28
- run: slopguard scan . --format json --output slopguard-report.json
29
-
30
- - name: Upload report
31
- if: always()
32
- uses: actions/upload-artifact@v4
33
- with:
34
- name: slopguard-report
35
- path: slopguard-report.json
@@ -1,30 +0,0 @@
1
- # Contributing to SlopGuard
2
-
3
- Thanks for the interest. SlopGuard is MIT-licensed and welcomes contributions.
4
-
5
- ## Quick start
6
-
7
- ```bash
8
- git clone https://github.com/hariomunknownslab/slopguard
9
- cd slopguard
10
- python -m venv .venv && source .venv/bin/activate
11
- make install
12
- make all # lint, typecheck, test
13
- ```
14
-
15
- ## Ground rules
16
-
17
- - `ruff check` and `ruff format` must pass cleanly.
18
- - `mypy --strict slopguard/` must pass with zero errors.
19
- - Test coverage on `slopguard/` must stay ≥ 85%.
20
- - No `Any`, no unjustified `# type: ignore`.
21
- - Do not add features outside the v0.1 scope without filing an issue first.
22
-
23
- ## Reporting hallucinated package names
24
-
25
- Open an issue with:
26
- - the package name (and ecosystem),
27
- - the LLM / tool that suggested it,
28
- - the prompt that produced the suggestion (if shareable).
29
-
30
- Curated reports feed the next iteration of the hallucination database.
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 SlopGuard
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.
@@ -1,106 +0,0 @@
1
- # CI integration
2
-
3
- SlopGuard is built to fail your CI before a slopsquatted package reaches
4
- `node_modules` or `site-packages`.
5
-
6
- ## GitHub Actions
7
-
8
- Copy `.github/workflows/slopguard.yml.example` into your repo as
9
- `.github/workflows/slopguard.yml`:
10
-
11
- ```yaml
12
- name: SlopGuard
13
- on:
14
- pull_request:
15
- push:
16
- branches: [main]
17
-
18
- jobs:
19
- slopguard:
20
- runs-on: ubuntu-latest
21
- steps:
22
- - uses: actions/checkout@v4
23
- - uses: actions/setup-python@v5
24
- with:
25
- python-version: "3.11"
26
- - run: pip install slopguard-cli
27
- - run: slopguard scan . --format json --output slopguard-report.json
28
- - uses: actions/upload-artifact@v4
29
- if: always()
30
- with:
31
- name: slopguard-report
32
- path: slopguard-report.json
33
- ```
34
-
35
- The workflow fails the job whenever SlopGuard exits non-zero. Tune
36
- `--fail-on hallucinated` if you want suspicious-tier findings to surface as
37
- warnings rather than block the build.
38
-
39
- ## Pre-commit
40
-
41
- SlopGuard isn't packaged as a pre-commit hook in v0.1 (see
42
- [deferred items](https://github.com/hariomunknownslab/slopguard) on the v0.2 roadmap),
43
- but a local hook is one line:
44
-
45
- ```yaml
46
- # .pre-commit-config.yaml
47
- repos:
48
- - repo: local
49
- hooks:
50
- - id: slopguard
51
- name: slopguard scan
52
- entry: slopguard scan
53
- language: system
54
- pass_filenames: false
55
- always_run: true
56
- ```
57
-
58
- ## Other CI providers
59
-
60
- `slopguard scan` is provider-agnostic. Anything that can install Python and
61
- run a shell command works:
62
-
63
- ```bash
64
- pip install slopguard-cli
65
- slopguard scan . --format json --output slopguard-report.json
66
- ```
67
-
68
- If a finding lands above the configured threshold, SlopGuard exits 1 and your
69
- pipeline fails.
70
-
71
- ## CI-friendly flags
72
-
73
- - `--format json --output <file>` — machine-readable artifact you can hand to
74
- a downstream summariser or commenter.
75
- - `--fail-on hallucinated` — strictest tier. Useful when you do not want
76
- suspicious findings to break the build but still want them in the artifact.
77
- - `--no-network` — useful in air-gapped CI. Detection falls back to the
78
- embedded seed DB + name-pattern signal.
79
- - `--concurrency` — bump up to 32 or 64 on a fast runner with many
80
- dependencies; the public registries tolerate it.
81
-
82
- ## Reading the JSON
83
-
84
- ```json
85
- {
86
- "slopguard_version": "0.1.0",
87
- "summary": { "total": 47, "clean": 44, "suspicious": 2, "hallucinated": 1, "errors": 0 },
88
- "findings": [
89
- {
90
- "name": "react-codeshift",
91
- "ecosystem": "npm",
92
- "manifest": "package.json",
93
- "risk": "hallucinated",
94
- "score": 0.95,
95
- "signals": [
96
- { "type": "hallucination_db_hit", "weight": 0.9, "detail": "Matched seed DB entry; recurrence 0.71 across 3 models." }
97
- ],
98
- "remediation": "Remove this dependency. Verify the package your AI suggested actually exists at the source you trust."
99
- }
100
- ],
101
- "exit_code": 1
102
- }
103
- ```
104
-
105
- The schema is documented in section 8 of the v0.1 spec. Treat it as a public
106
- API contract — version-bump SlopGuard if you ever need to break it.
@@ -1,77 +0,0 @@
1
- # How detection works
2
-
3
- SlopGuard scores each dependency by combining independent signals into a single
4
- risk score in `[0.0, 1.0]`, then maps the score to a tier:
5
-
6
- | Tier | Default range | Meaning |
7
- |---|---|---|
8
- | `hallucinated` | score ≥ 0.85 | High confidence the dependency is a hallucinated / slopsquat package. |
9
- | `suspicious` | 0.40 ≤ score < 0.85 | Worth a human look before installing. |
10
- | `clean` | score < 0.40 | No actionable evidence of risk. |
11
- | `error` | n/a | SlopGuard could not score the dependency (e.g. registry unreachable). |
12
-
13
- Thresholds are configurable in `.slopguard.yaml`.
14
-
15
- ## Signals
16
-
17
- | Signal | Trigger | Weight |
18
- |---|---|---|
19
- | `hallucination_db_hit` | Exact match (lowercased) in the embedded seed DB. | +0.90 |
20
- | `registry_not_found` | Registry returned 404 for the name. | +0.85 |
21
- | `very_recently_published` | First release < 7 days ago. | +0.35 |
22
- | `recently_published` | First release < 30 days ago. | +0.20 |
23
- | `low_downloads` | < 100 downloads (last month for npm, last week for PyPI). | +0.15 |
24
- | `new_publisher` | Publisher account < 30 days old. | +0.20 |
25
- | `single_release_new_account` | Publisher's only release; account < 60 days old. | +0.30 |
26
- | `levenshtein_typo` | Levenshtein distance 1–2 from a top-1000 popular package. | +0.25 |
27
- | `name_pattern_suspicious` | Matches a classic hallucination shape: `<stem>-(helpers?\|utils?\|async\|pro\|kit\|sdk\|tools?\|extras?\|plus\|next\|core)`. | +0.10 |
28
-
29
- The final score is the sum of triggered signal weights, capped at 1.0.
30
-
31
- ## Order of operations per dependency
32
-
33
- 1. **Hallucination-DB hit.** Short-circuit to `hallucinated`. Skip the registry
34
- probe unless `--verbose` is set (verbose still probes for completeness in the
35
- JSON report).
36
- 2. **`--no-network`.** Only the DB hit and `name_pattern_suspicious` apply.
37
- 3. **Registry probe.** Async, bounded by `--concurrency`, with timeouts and
38
- exponential back-off on 5xx / 429.
39
- 4. **404 → `registry_not_found` + stop.** The name doesn't exist on the
40
- registry; Levenshtein and name-pattern signals are still emitted for
41
- diagnostic value.
42
- 5. **200 → full signal sweep.** Compute every applicable signal from registry
43
- metadata.
44
-
45
- ## Edge cases
46
-
47
- - **Scoped npm packages (`@org/name`):** registry probe is skipped (private /
48
- internal packages are common at these names). They are scored `clean` unless
49
- the seed DB has them.
50
- - **Local file dependencies (`file:`, `link:`):** ignored entirely.
51
- - **Git URL dependencies:** out of scope for v0.1 scoring — emitted as `clean`
52
- with an informational `git_dependency` signal in the JSON output.
53
- - **Version pins:** not used for v0.1 detection. Version-specific signals are
54
- on the v0.2 roadmap.
55
-
56
- ## The hallucination database
57
-
58
- `slopguard/data/hallucinations_seed.json` ships embedded in the wheel and is
59
- loaded via `importlib.resources` at runtime. The current seed is **placeholder
60
- data**: the production database will be assembled from academic research on
61
- LLM-suggested packages plus a live probing harness. The schema is fixed at
62
- `schema_version: 1`; future updates will preserve backwards compatibility.
63
-
64
- ## Popular-package lists
65
-
66
- Top-1000 npm and PyPI names live in `slopguard/data/popular_packages.json` and
67
- back the Levenshtein-typo signal. The lists are synthesised for v0.1 and will
68
- be replaced with authoritative download-count rankings before release.
69
-
70
- ## What detection does *not* do (v0.1)
71
-
72
- - No live LLM probing.
73
- - No CVE / advisory matching.
74
- - No license scanning, no SBOM.
75
- - No supply-chain attestation (Sigstore, provenance, etc.).
76
-
77
- See the build spec, section 14, for the full list of deferred capabilities.
@@ -1,103 +0,0 @@
1
- # Usage
2
-
3
- ## Install
4
-
5
- ```bash
6
- pip install slopguard-cli
7
- # or
8
- brew install slopguard # formula ships in dist/homebrew/ in a later release
9
- ```
10
-
11
- The PyPI distribution name is `slopguard-cli`; the installed binary and
12
- Python import are still `slopguard`.
13
-
14
- ## Commands
15
-
16
- ### `slopguard scan`
17
-
18
- ```text
19
- slopguard scan [PATH] [OPTIONS]
20
- ```
21
-
22
- | Argument / Option | Default | Notes |
23
- |---|---|---|
24
- | `PATH` | current working directory | A project directory or a single manifest file. |
25
- | `--format` | `terminal` | `terminal` for Rich output, `json` for the wire format. |
26
- | `--output` | — | Write JSON to a file (only with `--format=json`). |
27
- | `--config` | auto-detected `.slopguard.yaml` | Path to a config file. SlopGuard walks up 3 parents from PATH. |
28
- | `--fail-on` | `suspicious` | `any` / `hallucinated` / `suspicious` / `none` — risk level that triggers exit 1. |
29
- | `--no-network` | off | Skip registry probes; rely on the seed DB + name-pattern signal. |
30
- | `--timeout` | 5.0s | Per-request timeout for registry probes. |
31
- | `--concurrency` | 16 | Maximum concurrent registry probes. |
32
- | `--verbose` / `-v` | off | Show debug logs. With `--verbose`, DB-hit findings still probe the registry for completeness. |
33
-
34
- ### `slopguard version`
35
-
36
- Prints the package version and exits 0.
37
-
38
- ## Exit codes
39
-
40
- | Code | Meaning |
41
- |---|---|
42
- | 0 | Scan complete, no findings at or above the `--fail-on` threshold. |
43
- | 1 | Scan complete, findings at or above the `--fail-on` threshold present. |
44
- | 2 | Could not run (bad input, no manifests found, IO error, etc.). |
45
-
46
- ## Manifest auto-detection
47
-
48
- `slopguard scan` walks the target directory up to 2 levels deep, skipping
49
- `node_modules`, `.venv`, `venv`, `__pycache__`, `.git`, `dist`, `build`.
50
-
51
- Recognised manifests:
52
-
53
- - `package.json`, `package-lock.json` (npm)
54
- - `requirements.txt`, `pyproject.toml`, `Pipfile` (Python)
55
-
56
- If a `package.json` and `package-lock.json` sit in the same directory, the
57
- lockfile is skipped — the manifest's directly-declared dependencies are what
58
- matter for slopsquat detection.
59
-
60
- ## `.slopguard.yaml`
61
-
62
- ```yaml
63
- # Every field is optional.
64
-
65
- ignore:
66
- packages: # exact package names to skip
67
- - internal-tool
68
- - my-private-pkg
69
- patterns: # regex patterns matched against package names
70
- - "^@mycompany/"
71
-
72
- fail_on: suspicious # any | hallucinated | suspicious | none
73
-
74
- network:
75
- enabled: true
76
- timeout_seconds: 5
77
- concurrency: 16
78
-
79
- scoring:
80
- suspicious_min_score: 0.4
81
- hallucinated_min_score: 0.85
82
- ```
83
-
84
- Merge precedence: **CLI flags > `.slopguard.yaml` > defaults.**
85
-
86
- ## Three useful invocations
87
-
88
- ```bash
89
- # 1. Default scan of the current directory.
90
- slopguard scan
91
-
92
- # 2. Scan a specific service in a monorepo.
93
- slopguard scan ./mono/services/api
94
-
95
- # 3. CI mode: JSON output, file artifact, fail only on hallucinated.
96
- slopguard scan --format json --output slopguard-report.json --fail-on hallucinated
97
- ```
98
-
99
- ## Performance
100
-
101
- A scan of ~200 dependencies completes in **under 10 seconds** on a residential
102
- broadband connection with `--concurrency 16`. Registry round-trips dominate;
103
- results are memoised in-process so duplicate dependency entries are free.
File without changes
File without changes