@brokkai/slopcop 0.0.3 → 0.0.5
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.
- package/README.md +157 -51
- package/native/darwin_amd64/slopcop +0 -0
- package/native/darwin_arm64/slopcop +0 -0
- package/native/linux_amd64/slopcop +0 -0
- package/native/linux_arm64/slopcop +0 -0
- package/native/windows_amd64/slopcop.exe +0 -0
- package/native/windows_arm64/slopcop.exe +0 -0
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -1,61 +1,102 @@
|
|
|
1
1
|
# SlopCop
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
**Static analysis deep enough for CI, fast enough to run on every edit.**
|
|
4
|
+
|
|
5
|
+
[](https://github.com/BrokkAi/slopcop/actions/workflows/ci.yml)
|
|
6
|
+
[](https://github.com/BrokkAi/slopcop/releases/latest)
|
|
7
|
+
[](https://www.npmjs.com/package/@brokkai/slopcop)
|
|
8
|
+
[](https://pypi.org/project/brokk-slopcop/)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://go.dev/)
|
|
11
|
+
|
|
12
|
+
`slopcop` sends one git patch, from the base commit to the working tree, to the
|
|
13
|
+
hosted check API at <https://slopcop.com>. The service applies it, runs the
|
|
14
|
+
hosted policy catalog plus the repository rules you selected, and returns the
|
|
15
|
+
report: every finding with its severity, the file and line that triggered it,
|
|
16
|
+
and the certainty behind it. The analysis is
|
|
17
|
+
[Bifrost](https://github.com/BrokkAi/bifrost), an open-source static analysis
|
|
18
|
+
engine rather than a language model, so a finding traces back to a rule instead
|
|
19
|
+
of to a guess.
|
|
20
|
+
|
|
21
|
+
There is no local analyzer and nothing to install per language: the CLI ships
|
|
22
|
+
the change and prints what comes back, and it never decides on its own that
|
|
23
|
+
there is nothing to check. The command is built for agents and one-shot CI: no
|
|
24
|
+
prompts, one request, and the analyzer's exit contract.
|
|
12
25
|
|
|
13
26
|
## Install
|
|
14
27
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
28
|
+
npm, PyPI, the release archive, and the PowerShell installer all install the
|
|
29
|
+
same release binary for macOS, Linux, and Windows on x64 and arm64, so
|
|
30
|
+
`slopcop version` reports which release it came from. The Go toolchain can
|
|
31
|
+
build that binary from source instead.
|
|
32
|
+
|
|
33
|
+
| Channel | Platforms | Needs |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| [npm](#npm) | macOS, Linux, Windows | Node 22 or newer |
|
|
36
|
+
| [PyPI](#pypi) | macOS, Linux, Windows | Python 3.9 or newer |
|
|
37
|
+
| [Release archive](#release-archive) | macOS, Linux, Windows | nothing |
|
|
38
|
+
| [PowerShell installer](#powershell-installer) | Windows | PowerShell |
|
|
39
|
+
| [Go](#go) | built from source | Go 1.25 or newer |
|
|
18
40
|
|
|
19
|
-
|
|
41
|
+
### npm
|
|
20
42
|
|
|
21
43
|
```console
|
|
22
|
-
|
|
44
|
+
npm install --global @brokkai/slopcop
|
|
45
|
+
slopcop --help
|
|
23
46
|
```
|
|
24
47
|
|
|
25
|
-
|
|
48
|
+
The tarball carries the release binary for every supported platform, so it
|
|
49
|
+
needs no Go toolchain. `npx @brokkai/slopcop` runs it without installing it.
|
|
26
50
|
|
|
27
|
-
|
|
28
|
-
building:
|
|
51
|
+
### PyPI
|
|
29
52
|
|
|
30
|
-
```
|
|
31
|
-
|
|
53
|
+
```console
|
|
54
|
+
pip install brokk-slopcop
|
|
32
55
|
```
|
|
33
56
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
57
|
+
`pipx install brokk-slopcop` or `uv tool install brokk-slopcop` puts it in an
|
|
58
|
+
environment of its own. The wheels carry the release binary, so no Go toolchain
|
|
59
|
+
is needed either. The package is `brokk-slopcop` because PyPI already has an
|
|
60
|
+
unrelated project named `slopcop`; the command it installs is still `slopcop`,
|
|
61
|
+
and `python -m brokk_slopcop` runs the same binary.
|
|
38
62
|
|
|
39
|
-
|
|
40
|
-
|
|
63
|
+
### Release archive
|
|
64
|
+
|
|
65
|
+
Each release publishes `slopcop_v<version>_<os>_<arch>.tar.gz` (`.zip` on
|
|
66
|
+
Windows) holding the binary, `README.md`, and `LICENSE`, plus a `checksums.txt`
|
|
67
|
+
covering every archive. Download them from
|
|
68
|
+
<https://github.com/BrokkAi/slopcop/releases/latest> and check the sha256
|
|
69
|
+
before unpacking:
|
|
41
70
|
|
|
42
71
|
```console
|
|
43
|
-
|
|
44
|
-
|
|
72
|
+
ver=0.0.3; os=linux; arch=amd64 # darwin/arm64 on Apple silicon
|
|
73
|
+
base=https://github.com/BrokkAi/slopcop/releases/download/v$ver
|
|
74
|
+
curl -fsSLO "$base/slopcop_v${ver}_${os}_${arch}.tar.gz"
|
|
75
|
+
curl -fsSLO "$base/checksums.txt"
|
|
76
|
+
grep "${os}_${arch}" checksums.txt | sha256sum -c - # shasum -a 256 -c - on macOS
|
|
77
|
+
tar -xzf "slopcop_v${ver}_${os}_${arch}.tar.gz" slopcop
|
|
78
|
+
sudo install -m 755 slopcop /usr/local/bin/slopcop
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### PowerShell installer
|
|
82
|
+
|
|
83
|
+
```powershell
|
|
84
|
+
irm https://raw.githubusercontent.com/BrokkAi/slopcop/master/install.ps1 | iex
|
|
45
85
|
```
|
|
46
86
|
|
|
47
|
-
|
|
87
|
+
It takes the latest release, verifies the archive against `checksums.txt`,
|
|
88
|
+
installs `slopcop.exe` to `%LOCALAPPDATA%\Programs\slopcop`, and adds that
|
|
89
|
+
directory to the user `Path`. `SLOPCOP_VERSION`, `SLOPCOP_INSTALL_DIR`, and
|
|
90
|
+
`SLOPCOP_NO_MODIFY_PATH` override its defaults.
|
|
48
91
|
|
|
49
|
-
|
|
50
|
-
so it needs no Go toolchain either:
|
|
92
|
+
### Go
|
|
51
93
|
|
|
52
94
|
```console
|
|
53
|
-
|
|
95
|
+
go install github.com/BrokkAi/slopcop/cmd/slopcop@latest
|
|
54
96
|
```
|
|
55
97
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
brokk_slopcop` runs the same binary.
|
|
98
|
+
Go 1.25 or newer is required to build. A plain `go install` reports `dev` as
|
|
99
|
+
its version; in a clone, `make install` stamps the version from `git describe`.
|
|
59
100
|
|
|
60
101
|
## Enable it in an agent
|
|
61
102
|
|
|
@@ -69,9 +110,12 @@ harness is present, and names what it did:
|
|
|
69
110
|
| `~/.claude/skills/slopcop/` | Claude Code, opencode |
|
|
70
111
|
| `$CODEX_HOME/skills/slopcop/`, or `~/.codex/skills/slopcop/` | Codex home |
|
|
71
112
|
|
|
72
|
-
A skill that is already there is left alone, so
|
|
73
|
-
|
|
74
|
-
|
|
113
|
+
A skill that is already there is left alone by init, so running it again is
|
|
114
|
+
safe. `slopcop login` and every check also install the skill in those
|
|
115
|
+
directories, rewriting one that differs from the skill bundled into the binary,
|
|
116
|
+
so an agent follows the instructions of the slopcop version it runs; local
|
|
117
|
+
edits to an installed skill do not survive them. `slopcop init --no-skill`
|
|
118
|
+
skips the install and any update of it.
|
|
75
119
|
|
|
76
120
|
## Sign in
|
|
77
121
|
|
|
@@ -118,10 +162,11 @@ Flags:
|
|
|
118
162
|
| `--root PATH` | repository to check (default `.`) |
|
|
119
163
|
| `--base REV` | base commit or revision for the change |
|
|
120
164
|
| `--format human\|json\|sarif` | report format (default `human`) |
|
|
121
|
-
| `--fail-on never\|finding\|note\|warning\|error` | exit-1 threshold (default `finding`) |
|
|
165
|
+
| `--fail-on never\|finding\|note\|warning\|error` | exit-1 threshold for new findings (default `finding`) |
|
|
166
|
+
| `--show-existing` | also list the findings that were already in the code |
|
|
122
167
|
| `--policy PATH` | repository-relative `.rqlp` file to evaluate (repeatable) |
|
|
123
168
|
| `--no-policy-discovery` | skip `.slopcop/policies` rules |
|
|
124
|
-
| `--timeout DURATION` |
|
|
169
|
+
| `--timeout DURATION` | how long to wait for the result (default `10m`) |
|
|
125
170
|
| `--verbose` | print the resolved request to stderr |
|
|
126
171
|
|
|
127
172
|
### What is sent
|
|
@@ -141,21 +186,76 @@ Every check also runs the hosted catalog. Rules under
|
|
|
141
186
|
`.slopcop/policies/**/*.rqlp` are added automatically unless
|
|
142
187
|
`--no-policy-discovery` is set.
|
|
143
188
|
|
|
189
|
+
### New and pre-existing findings
|
|
190
|
+
|
|
191
|
+
A check fails only on findings the change introduced or touched: the service
|
|
192
|
+
marks a finding new when it is in a file the change writes and its lines meet a
|
|
193
|
+
line the change added, or the line beside one it removed. Findings that were
|
|
194
|
+
already in the code are counted, never fail the check, and are listed only with
|
|
195
|
+
`--show-existing`. A change that introduces nothing exits `0`, however many
|
|
196
|
+
findings the repository already holds.
|
|
197
|
+
|
|
198
|
+
### Ignore a false positive
|
|
199
|
+
|
|
200
|
+
Each finding a check reports carries an `id`. When a finding is a false
|
|
201
|
+
positive, ignore it:
|
|
202
|
+
|
|
203
|
+
```console
|
|
204
|
+
slopcop ignore 0f8fad5b-d9cb-469f-a165-70867728950e
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
That finding is not reported again for this repository. Ignoring covers that
|
|
208
|
+
one finding, its rule plus its place in the code, in its repository for your
|
|
209
|
+
workspace; the rule keeps reporting everything else. Ignoring a finding twice
|
|
210
|
+
is fine. `ignore` uses the same login and service URL as a check, exits `0`
|
|
211
|
+
with a one-line confirmation, and otherwise exits `2` with the service's
|
|
212
|
+
message and remedy; `finding_not_found` means the id is unknown or comes from a
|
|
213
|
+
check outside your workspace.
|
|
214
|
+
|
|
144
215
|
### Output and exit codes
|
|
145
216
|
|
|
146
217
|
The service answers structured data; the CLI renders it. `human` prints one
|
|
147
|
-
block per finding,
|
|
148
|
-
|
|
149
|
-
`
|
|
150
|
-
|
|
218
|
+
block per new finding, with an `ID:` line when the service names one, then the
|
|
219
|
+
pre-existing ones with `--show-existing`, a
|
|
220
|
+
summary line such as `1 new finding across 1 file(s); 72 already in the code
|
|
221
|
+
(--show-existing lists them) | Analysis complete`, and any omitted or
|
|
222
|
+
incomplete checks. `json` prints `status`, `baseCommit`, `summary`
|
|
223
|
+
(`newFindings` and `existingFindings` count the split), `findings` (each with
|
|
224
|
+
`new` and its `id`), `incomplete`, and `failure` when the analysis did not
|
|
225
|
+
complete. `sarif` prints a SARIF 2.1.0 log whose results carry `baselineState`
|
|
226
|
+
`new` or `unchanged` and the finding id in `properties["slopcop.findingId"]`. `--format` and `--show-existing` only change the rendering, never
|
|
227
|
+
the request, so the service answers the same check whichever is used.
|
|
151
228
|
|
|
152
229
|
| Exit | Meaning |
|
|
153
230
|
| --- | --- |
|
|
154
|
-
| `0` | Check completed;
|
|
155
|
-
| `1` | A finding crossed `--fail-on` |
|
|
156
|
-
| `2` |
|
|
231
|
+
| `0` | Check completed; no new finding crossed the `--fail-on` level |
|
|
232
|
+
| `1` | A new finding crossed `--fail-on` |
|
|
233
|
+
| `2` | No new finding crossed `--fail-on`, but a check was incomplete; or the CLI or service failed |
|
|
234
|
+
| `3` | The check was still running when `--timeout` ran out |
|
|
235
|
+
|
|
236
|
+
An inconclusive check fails the check only when it concerns a file the
|
|
237
|
+
change writes. One about other files is listed on an `Inconclusive outside
|
|
238
|
+
the change` line (`inconclusiveElsewhere` in `json`, a `note` notification in
|
|
239
|
+
`sarif`) and never changes the exit code. A check that timed out counts
|
|
240
|
+
wherever it is. The service can place an inconclusive check only once Bifrost
|
|
241
|
+
reports which files it concerns; until then every one counts as in the change.
|
|
157
242
|
|
|
158
243
|
The service applies `--fail-on` and sets the status; the exit code follows it.
|
|
244
|
+
The CLI always sends `--fail-on`, defaulting to `finding`: a check fails only
|
|
245
|
+
on findings the change introduced, so any of them, a note or an unrated one
|
|
246
|
+
included, is worth fixing before the change lands. The service's own default
|
|
247
|
+
for a request without `failOn` is Bifrost's `warning`; pass `--fail-on warning`
|
|
248
|
+
to match it.
|
|
249
|
+
New findings that cross `--fail-on` exit `1` even when some check did not
|
|
250
|
+
complete.
|
|
251
|
+
|
|
252
|
+
While the service answers `check_running`, the CLI waits the `Retry-After` it
|
|
253
|
+
names and asks again until `--timeout` runs out; every ask attaches to the same
|
|
254
|
+
running check. If it is still running then, the CLI exits `3`, prints the
|
|
255
|
+
service's message and remedy on stderr, and in `json` prints
|
|
256
|
+
`{"status": "pending", "retryAfter": 5, "message": …, "remedy": …}` on stdout
|
|
257
|
+
(`sarif` prints a run with `slopcop.status` `pending`). Running the same check
|
|
258
|
+
again picks up the same analysis.
|
|
159
259
|
|
|
160
260
|
Service failures print the closed contract exactly: message, remedy, and any
|
|
161
261
|
install URL. The codes, messages, and remedies are defined by the service in
|
|
@@ -164,10 +264,6 @@ rewrite them. The remedies name no client, so when one says to sign in the CLI
|
|
|
164
264
|
adds the `slopcop login` command after it. A failed request prints no report
|
|
165
265
|
on stdout.
|
|
166
266
|
|
|
167
|
-
While SlopCop is still indexing the repository, the service answers
|
|
168
|
-
`indexing_in_progress` at once instead of running the check. The CLI prints it
|
|
169
|
-
and exits `2` without waiting or retrying.
|
|
170
|
-
|
|
171
267
|
## API
|
|
172
268
|
|
|
173
269
|
The CLI calls `POST <service>/v1/check` with a bearer token:
|
|
@@ -184,9 +280,19 @@ The CLI calls `POST <service>/v1/check` with a bearer token:
|
|
|
184
280
|
|
|
185
281
|
The service rejects any other field. The response carries `status`,
|
|
186
282
|
`baseCommit`, `applied`, `summary`, `findings`, `incomplete`, and `failure`
|
|
187
|
-
when the analysis did not complete.
|
|
283
|
+
when the analysis did not complete. Against a service from before findings
|
|
284
|
+
were marked `new`, the CLI treats every finding as new, as that service gated
|
|
285
|
+
on all of them. Non-2xx responses carry `code`, `message`,
|
|
188
286
|
`remedy`, `retryable`, and an optional `installUrl`.
|
|
189
287
|
|
|
288
|
+
Each finding in the response carries an `id`; a service from before findings
|
|
289
|
+
could be ignored omits it.
|
|
290
|
+
|
|
291
|
+
`slopcop ignore <id>` calls `POST <service>/v1/ignore` with the same bearer
|
|
292
|
+
token and `{"findingId": "<id>"}`, and gets back
|
|
293
|
+
`{"findingId": "<id>", "status": "ignored"}`. Failures use the same closed
|
|
294
|
+
contract, including `finding_not_found`.
|
|
295
|
+
|
|
190
296
|
`slopcop login` uses the device flow: `POST /api/device` returns a
|
|
191
297
|
`deviceCode`, `userCode`, `verificationUri`, `expiresIn`, and `interval`, and
|
|
192
298
|
`POST /api/token` returns `202` while pending or `200` with a `token` once
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brokkai/slopcop",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.5",
|
|
4
|
+
"description": "Static analysis for coding agents and CI: check a change through the hosted SlopCop API",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agents",
|
|
7
|
+
"ai-agent",
|
|
8
|
+
"ci",
|
|
9
|
+
"cli",
|
|
10
|
+
"code-review",
|
|
11
|
+
"coding-agent",
|
|
12
|
+
"git",
|
|
13
|
+
"sarif",
|
|
14
|
+
"static-analysis"
|
|
15
|
+
],
|
|
5
16
|
"license": "Apache-2.0",
|
|
6
17
|
"repository": {
|
|
7
18
|
"type": "git",
|