Metadata-Version: 2.5
Name: slopstopper-cli
Version: 0.18.0
Summary: A Python CLI plus GitHub Actions workflows that run security, hygiene and reliability checks on every PR. One command to install into any repo.
Project-URL: Homepage, https://slopstopper.dev
Project-URL: Source, https://github.com/hungovercoders/slopstopper
Project-URL: Issues, https://github.com/hungovercoders/slopstopper/issues
Project-URL: Documentation, https://slopstopper.dev
Project-URL: Changelog, https://github.com/hungovercoders/slopstopper/blob/main/CHANGELOG.md
Project-URL: Acknowledgements, https://github.com/hungovercoders/slopstopper/blob/main/ATTRIBUTIONS.md
Author: Richard Griffiths
Maintainer-email: Richard Griffiths <griff182uk@googlemail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: accessibility,checks,ci,lighthouse,linting,playwright,quality,security,slopstopper
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: System :: Software Distribution
Requires-Python: >=3.11
Requires-Dist: lizard>=1.17
Provides-Extra: test
Requires-Dist: pytest>=7; extra == 'test'
Description-Content-Type: text/markdown

# slopstopper-cli

A Python CLI plus GitHub Actions workflows that run security, hygiene and reliability checks on every PR. One command to install into any repo. This package is the CLI.

> **Status: Beta.** Every check in the [public catalogue](https://slopstopper.dev/features.html) runs through this package. The CI workflows under `.github/workflows/ss-*.yml` install the pinned `slopstopper-cli` via `jdx/mise-action` and call `slopstopper run <category>:<check>`, which is the same code path you use locally.

## Install

Quick standalone try (unpinned):

```bash
pipx install slopstopper-cli
slopstopper --version
slopstopper checks list
slopstopper doctor
```

> Published to PyPI on every release tag. `pipx upgrade slopstopper-cli` pulls the latest. Each release is also attached to the [latest GitHub Release](https://github.com/hungovercoders/slopstopper/releases/latest) with a Sigstore build-provenance attestation. Verify it with `gh attestation verify <wheel> --owner hungovercoders`.

For a repo you'll keep, install the pinned suite so local and CI run the same version:

```bash
curl -fsSL https://raw.githubusercontent.com/hungovercoders/slopstopper/main/install.sh | bash
```

> Requires [mise](https://mise.jdx.dev). `install.sh` pins `slopstopper-cli` + `task` in `mise.toml` (the single source of truth both local runs and CI read) and seeds the `ss-*.yml` workflows. Move the pin with `install.sh --upgrade-cli` / `--cli-version`.

Development (editable, from a clone of this repo):

```bash
pip install -e ./cli
slopstopper run hygiene:docs-size
```

## CLI surface

```text
slopstopper run <category>:<check>             # run a check, write reports under .ss/reports/
slopstopper emit <c>:<n> --target {pr-comment,issue}
slopstopper discover <check> --event <e>       # resolve pages.<check> from sitemap / changed / list
slopstopper config get <key> [<default>]       # read .slopstopper.yml
slopstopper templates {list, path <n>, eject <n>}   # inspect / customise bundled templates
slopstopper serve                              # bundled static server (auto-detects worker/headers.json)
slopstopper checks list [--category <c>] [--json]
slopstopper doctor                             # verify external tools are installed
slopstopper profile {list, show, expand <n>, detect}   # project-shape profile (ui / api / library)
slopstopper --quiet …                          # suppress decorative output (CI logs)
```

`slopstopper` with no args prints a banner of the commands above plus a quick-start block.

## Run the tests

```bash
# From the repo root:
task -t cli/Taskfile.yml test

# Or from cli/:
task test

# Filter to a single test:
task -t cli/Taskfile.yml test -- -k docs_size
```

From the repo root `task contributing:test` is an alias for the same target. It is also what CI runs (see [`ci-cli.yml`](https://github.com/hungovercoders/slopstopper/blob/main/.github/workflows/ci-cli.yml)), so local and CI invocations stay in sync. The Taskfile creates and reuses a project-local venv at `cli/.venv/` (gitignored) so it doesn't conflict with system Python under PEP 668.

This workflow is slopstopper-internal. It is **not** part of the distributed `ss-*-check.yml` suite and is never seeded into adopter repos.

## Layout

- `slopstopper/cli.py` is the argparse dispatcher and prints the bare-invocation banner
- `slopstopper/output.py` holds the shared formatters (running / success / warn / error / footer / `--quiet`)
- `slopstopper/config.py` reads `.slopstopper.yml` (stdlib-only YAML subset)
- `slopstopper/templates.py` resolves bundled templates and backs the `templates {list, path, eject}` API
- `slopstopper/emit.py` wraps the `gh` CLI to post PR comments and main-branch issues
- `slopstopper/discovery.py` resolves the pages to audit for reliability checks
- `slopstopper/profiles.py` holds the project-shape profiles. It resolves which workflows a repo carries with `(profile.disables − workflows.enabled) ∪ workflows.disabled` (explicit `workflows.disabled` wins if the same workflow is listed in both), plus the check → workflow map. `install.sh` imports this module directly, so it is the only implementation
- `slopstopper/checks/` holds one module per check; the registry is in `__init__.py`
- `slopstopper/data/` holds the bundled Playwright specs, lighthouserc dev/prod, server.js and `profiles.json`

## Adding a check

A check is more than a module. It needs a workflow, a Task target, profile classification, a badge label, docs, site copy and a skills entry. Follow the single checklist in the **"New quality check"** row of [`AGENTS.md`](https://github.com/hungovercoders/slopstopper/blob/main/AGENTS.md) rather than a summary here. Inside this package, `slopstopper/checks/<name>.py` exposes `run(args) -> int` (0 pass, 1 findings, 2 could-not-run) and registers in `checks/__init__.py`'s `REGISTRY`. Its docstring's first line is what `slopstopper checks list` prints. It prints through `from slopstopper import output` so `--quiet` works, and declares a `META` dict if `emit.py` should post it.

## Skills for agents

The duo under [`.claude/skills/slopstopper-{install,triage}/`](https://github.com/hungovercoders/slopstopper/tree/main/.claude/skills) is the long-form playbook for Claude Code agents working with this CLI. Update them when you add or rename a check, env var, `task ss:*` target, or profile.

## Acknowledgements

The only third-party Python dependency of slopstopper-cli is [`lizard`](https://pypi.org/project/lizard/), the complexity engine behind `hygiene:complexity`, which must live in the same interpreter the CLI runs from. Every other tool (Playwright, axe-core, Lighthouse, Semgrep, Gitleaks, Trivy, ZAP) is invoked via `subprocess` only. Full credit, licences and upstream links for every tool we drive live in [`ATTRIBUTIONS.md`](https://github.com/hungovercoders/slopstopper/blob/main/ATTRIBUTIONS.md).

## License

MIT; the full text is in [LICENSE](./LICENSE).
