@chimix/agentscan 0.4.0 → 0.5.0
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 +77 -41
- package/dist/cli.js +1038 -772
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<img src="https://img.shields.io/badge/checks-
|
|
9
|
-
<img src="https://img.shields.io/badge/tests-
|
|
8
|
+
<img src="https://img.shields.io/badge/checks-26-111111?style=flat-square" alt="26 checks">
|
|
9
|
+
<img src="https://img.shields.io/badge/tests-226%20passing-111111?style=flat-square" alt="226 tests">
|
|
10
10
|
<img src="https://img.shields.io/badge/network-none-111111?style=flat-square" alt="No network">
|
|
11
11
|
<img src="https://img.shields.io/badge/writes-none-111111?style=flat-square" alt="Writes nothing">
|
|
12
12
|
<img src="https://img.shields.io/badge/runs%20on-node%20%C2%B7%20bun-111111?style=flat-square" alt="Node or Bun">
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
18
|
-
<strong>
|
|
18
|
+
<strong>26 checks · 4.1k lines · 0 network calls · every check sourced to a published spec line</strong><br>
|
|
19
19
|
<sub>Alpha. An earlier build reported 37 findings across 17 real projects of which <strong>25 were false</strong> — two checks had been written from what real projects looked like instead of from the spec. Both were deleted, and every check that survived is recorded in <a href="docs/spec/">docs/spec/</a> with the URL it came from and the date it was read. That story is the reason this tool exists in its current shape.</sub>
|
|
20
20
|
</p>
|
|
21
21
|
|
|
@@ -47,12 +47,11 @@ think you have has silently not existed for six weeks.
|
|
|
47
47
|
```console
|
|
48
48
|
$ agentscan check
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
evidence: hook PreToolUse @ …/.claude/settings.json
|
|
50
|
+
ERROR rule:hook.missing-script
|
|
51
|
+
PreToolUse hook points at a script that does not exist: .claude/hooks/guard-destructive-bash.js
|
|
52
|
+
PreToolUse @ .claude/settings.json · .claude/hooks/guard-destructive-bash.js
|
|
54
53
|
|
|
55
|
-
Summary:
|
|
54
|
+
Summary: 1 error · score 90/100
|
|
56
55
|
```
|
|
57
56
|
|
|
58
57
|
That is the whole category: **a config file asserting something that is not true
|
|
@@ -65,7 +64,7 @@ No AI, no network, no heuristics. Read the config, read the disk, compare:
|
|
|
65
64
|
```
|
|
66
65
|
1. Discover .claude/ .agents/ .mcp.json AGENTS.md skills-lock.json
|
|
67
66
|
2. Extract immutable facts — never re-read during checking
|
|
68
|
-
3. Check
|
|
67
|
+
3. Check 26 checks, each against one published spec line
|
|
69
68
|
4. Report text · --json · --output prompt (handoff for a fixing agent)
|
|
70
69
|
```
|
|
71
70
|
|
|
@@ -84,8 +83,16 @@ A check here has to point at a spec line. If it cannot, it does not ship.
|
|
|
84
83
|
|
|
85
84
|
## Try it in 30 seconds
|
|
86
85
|
|
|
87
|
-
Run
|
|
88
|
-
|
|
86
|
+
No project handy? Run the built-in demo — it builds a throwaway fixture with the
|
|
87
|
+
killer case (a `PreToolUse` hook pointing at a missing script), prints the human
|
|
88
|
+
report, and deletes the fixture:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npx @chimix/agentscan@latest demo
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Against a real project, it reads that tree, writes nothing, and never leaves
|
|
95
|
+
your machine:
|
|
89
96
|
|
|
90
97
|
```bash
|
|
91
98
|
cd ~/your-project
|
|
@@ -104,8 +111,9 @@ bun add -d @chimix/agentscan # then: bunx agentscan check
|
|
|
104
111
|
```
|
|
105
112
|
|
|
106
113
|
Point it at a project that actually has agent config — a `.claude/` directory,
|
|
107
|
-
an `.mcp.json`, an `AGENTS.md`.
|
|
108
|
-
|
|
114
|
+
an `.mcp.json`, an `AGENTS.md`. A directory with agent config and no
|
|
115
|
+
`package.json` is still scannable. On a directory with neither it exits with a
|
|
116
|
+
clear error.
|
|
109
117
|
|
|
110
118
|
```bash
|
|
111
119
|
# what it could possibly report, before you run it
|
|
@@ -152,6 +160,7 @@ bunx agentscan check --verbose # include KEEP and info-severity findings
|
|
|
152
160
|
bunx agentscan check --fail-on warning
|
|
153
161
|
bunx agentscan check --global # also scan global skill dirs
|
|
154
162
|
|
|
163
|
+
bunx agentscan demo # one-shot fixture (no project required)
|
|
155
164
|
bunx agentscan explain <findingId> # detail one finding
|
|
156
165
|
bunx agentscan rules # every check + rule id that can fire
|
|
157
166
|
bunx agentscan init # write .agentscanrc.json
|
|
@@ -179,21 +188,21 @@ Flags for `check`:
|
|
|
179
188
|
```text
|
|
180
189
|
┌─────┐ 40/100 broken · touchagency
|
|
181
190
|
│ ✕ ✕ │ ██████████░░░░░░░░░░░░░░░
|
|
182
|
-
│ ⌒ │ 6
|
|
191
|
+
│ ⌒ │ 6 error · 4 info hidden (--verbose)
|
|
183
192
|
└─────┘
|
|
184
193
|
|
|
185
|
-
agentscan v0.
|
|
194
|
+
agentscan v0.5.0 — touchagency
|
|
186
195
|
|
|
187
196
|
Scanned: 46 deps · 54 skills · 1 mcp · 2 agents · packageManager=bun
|
|
188
197
|
|
|
189
|
-
|
|
190
|
-
|
|
198
|
+
ERROR rule:hook.missing-script ×6
|
|
199
|
+
Hook points at a script that does not exist
|
|
191
200
|
PostToolUse @ .claude/settings.json · .claude/hooks/notify-related-tests.js
|
|
192
201
|
PreToolUse @ .claude/settings.json · .claude/hooks/guard-destructive-bash.js
|
|
193
202
|
PreToolUse @ .claude/settings.json · .claude/hooks/protect-artists-json.js
|
|
194
203
|
PreToolUse @ .claude/settings.json · .claude/hooks/protect-env.js
|
|
195
204
|
|
|
196
|
-
Summary: 6
|
|
205
|
+
Summary: 6 error · 4 info hidden (--verbose) · score 40/100 broken
|
|
197
206
|
```
|
|
198
207
|
|
|
199
208
|
On a terminal the header is coloured green, yellow or red and the face tracks
|
|
@@ -201,14 +210,15 @@ the score. Redirect or pipe it and you get exactly the text above, with no
|
|
|
201
210
|
escape sequences — the header box is dropped too, so `--json`, `--output
|
|
202
211
|
prompt`, CI logs and `--copy` are unchanged by any of this.
|
|
203
212
|
|
|
204
|
-
The `
|
|
205
|
-
|
|
213
|
+
The `Scanned:` line is orientation only — which project, how big. The summary
|
|
214
|
+
lists severities (error / warning / info); a clean project prints
|
|
215
|
+
`Summary: no findings`. Score and `--fail-on` still use severity under the hood.
|
|
206
216
|
|
|
207
217
|
JSON shape (abridged):
|
|
208
218
|
|
|
209
219
|
```json
|
|
210
220
|
{
|
|
211
|
-
"version": "0.
|
|
221
|
+
"version": "0.5.0",
|
|
212
222
|
"root": "/path/to/project",
|
|
213
223
|
"factsSummary": {
|
|
214
224
|
"packageManager": "bun",
|
|
@@ -392,7 +402,7 @@ Every check lives in `src/checks/` and runs on every `check`. `agentscan rules`
|
|
|
392
402
|
lists all of them with their ids; `agentscan explain <id>` details any finding.
|
|
393
403
|
|
|
394
404
|
Most validate one discovered item against its own file on disk. The five
|
|
395
|
-
`budget.*`
|
|
405
|
+
`budget.*` entries at the bottom judge aggregate size instead —
|
|
396
406
|
they are all **info**, they are sourced to `docs/spec/thresholds.md`, and they
|
|
397
407
|
are retuned through `thresholds` in `.agentscanrc.json` rather than switched
|
|
398
408
|
off.
|
|
@@ -402,10 +412,14 @@ off.
|
|
|
402
412
|
| `config.unreadable` | error | A config file that is not valid JSON, so whatever it declares is silently not in effect |
|
|
403
413
|
| `hook.missing-script` | error | A registered hook whose script does not exist — it never runs |
|
|
404
414
|
| `hook.unknown-event` | error | A hook registered under an event name that is never dispatched |
|
|
405
|
-
| `agent.missing-frontmatter` |
|
|
406
|
-
| `agent.missing-description` |
|
|
407
|
-
| `
|
|
408
|
-
| `
|
|
415
|
+
| `agent.missing-frontmatter` | error | An agent definition with no `---` block |
|
|
416
|
+
| `agent.missing-description` | error | Agent frontmatter has no `description` |
|
|
417
|
+
| `agent.missing-name` | error | Agent frontmatter has no `name` |
|
|
418
|
+
| `agent.invalid-name` | error | Agent name is not lowercase letters, numbers, and hyphens |
|
|
419
|
+
| `agent.duplicate-name` | error | Multiple agent files declare the same name |
|
|
420
|
+
| `mcp.no-launch` | error | An MCP server with neither `command` nor `url` — unlaunchable by schema |
|
|
421
|
+
| `mcp.command-missing` | error | An MCP `command` that is a path-like value whose file does not exist on disk |
|
|
422
|
+
| `mcp.url-without-type` | error | A remote MCP server with a `url` but no `type` — read as stdio, misconfigured by schema, and skipped |
|
|
409
423
|
| `mcp.hardcoded-secret` | error | A token-shaped literal in MCP config (the value is never echoed back) |
|
|
410
424
|
| `mcp.literal-env` | warning | Long literal `env` values that should be `${VAR}` |
|
|
411
425
|
| `skill.missing-skill-md` | warning | A directory under a skill path with no `SKILL.md` |
|
|
@@ -419,9 +433,8 @@ off.
|
|
|
419
433
|
| `skill.no-lockfile` | info | Skills present with no lockfile at all (only with `requireLock`) |
|
|
420
434
|
|
|
421
435
|
Agent definitions are checked for structure only. An agent's frontmatter `name`
|
|
422
|
-
is
|
|
423
|
-
|
|
424
|
-
and a test guards against re-adding that check. Model identifiers and tool names
|
|
436
|
+
is not compared to the filename; it must simply be a valid lowercase identifier
|
|
437
|
+
and unique. Model identifiers and tool names
|
|
425
438
|
are likewise not validated: both would need a hardcoded list, which is the shape
|
|
426
439
|
that already shipped a false error. See [plans/003](plans/003-validate-agent-definitions.md).
|
|
427
440
|
|
|
@@ -433,13 +446,14 @@ references measured across 17 projects, 1645 resolved skill-relative and 12 only
|
|
|
433
446
|
at the root. Fenced code blocks are stripped first: a path in an example is
|
|
434
447
|
illustration, not a pointer.
|
|
435
448
|
|
|
436
|
-
`hook.missing-script`
|
|
437
|
-
|
|
438
|
-
(`a && b`, `$(...)`, pipes)
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
`$CLAUDE_PROJECT_DIR` is expanded — other variables are left alone rather
|
|
442
|
-
guessed at.
|
|
449
|
+
`hook.missing-script` and `mcp.command-missing` are deliberately conservative.
|
|
450
|
+
A value is only resolved when it is path-like and the answer is certain; shell
|
|
451
|
+
programs (`a && b`, `$(...)`, pipes), bare PATH binaries (`npx`, `uvx`), and
|
|
452
|
+
unresolved env vars are skipped. A false "broken" on a working `npx` server
|
|
453
|
+
would be worse than silence. `node -e "<code>"` is never treated as a path.
|
|
454
|
+
Only `$CLAUDE_PROJECT_DIR` is expanded — other variables are left alone rather
|
|
455
|
+
than guessed at. Schema checks judge misconfiguration, not whether a correctly
|
|
456
|
+
shaped entry will start at runtime.
|
|
443
457
|
|
|
444
458
|
Checks are written against the published specs, not against what happens to
|
|
445
459
|
appear in real projects. Two that were written the other way round shipped as
|
|
@@ -461,7 +475,9 @@ When adding a check, add its spec line there first.
|
|
|
461
475
|
the `computedHash` in `skills-lock.json` is the obvious `refresh` source; the
|
|
462
476
|
hash algorithm used by the installing tool is not documented here, and it is
|
|
463
477
|
not reproducible from `SKILL.md` bytes alone, so it is not implemented.
|
|
464
|
-
- **
|
|
478
|
+
- **Runtime split.** Source development and the composite Action use Bun; the
|
|
479
|
+
published `dist/cli.js` runs on Node 20.11+ or Bun. The source entrypoint uses
|
|
480
|
+
Bun's `import.meta.dir` / `import.meta.main` and is not the Node entrypoint.
|
|
465
481
|
- Policy files are read up to 100 KB, so `policyLines` undercounts past that.
|
|
466
482
|
|
|
467
483
|
## Development
|
|
@@ -480,14 +496,34 @@ bun run src/cli.ts check tests/fixtures/lock-drift
|
|
|
480
496
|
| `test` | `bun test` |
|
|
481
497
|
| `check` | `bun run src/cli.ts check` |
|
|
482
498
|
|
|
499
|
+
### Release checklist
|
|
500
|
+
|
|
501
|
+
Before publishing a release:
|
|
502
|
+
|
|
503
|
+
1. Confirm `package.json` and `src/version.ts` contain the same version.
|
|
504
|
+
2. Run `bun run build`, then verify `node dist/cli.js --version` prints it.
|
|
505
|
+
3. Run `bun run typecheck`, `bun test`, and `bun run spec:check`.
|
|
506
|
+
4. Refresh the test-count badge and version examples above from that release run.
|
|
507
|
+
|
|
483
508
|
## Design docs
|
|
484
509
|
|
|
485
510
|
**This README is the source of truth for current behavior.** The documents under
|
|
486
511
|
`docs/superpowers/specs/` are the original design and are **superseded** —
|
|
487
|
-
several decisions changed while building: Bun-only runtime
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
(`plans/010`). Read
|
|
512
|
+
several decisions changed while building: the original Bun-only runtime claim was
|
|
513
|
+
superseded by a Node-compatible published bundle, the dep-to-skill map and its
|
|
514
|
+
"orphan" heuristic dropped in favour of `skills-lock.json`, budget checks added,
|
|
515
|
+
structural checks added, and the YAML rule engine deleted (`plans/010`). Read
|
|
516
|
+
them as history, not as behavior.
|
|
517
|
+
|
|
518
|
+
## Skill
|
|
519
|
+
|
|
520
|
+
A Cursor / Agent Skills file lives at [`skills/agentscan/SKILL.md`](skills/agentscan/SKILL.md). Copy the folder so the agent runs the audit before it edits hooks or claims a guard is in place:
|
|
521
|
+
|
|
522
|
+
```bash
|
|
523
|
+
cp -R skills/agentscan .cursor/skills/agentscan
|
|
524
|
+
# or: .agents/skills/agentscan
|
|
525
|
+
# or: .claude/skills/agentscan
|
|
526
|
+
```
|
|
491
527
|
|
|
492
528
|
## License
|
|
493
529
|
|