@chimix/agentscan 1.0.0 → 1.1.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/CHANGELOG.md +143 -0
- package/README.md +147 -65
- package/dist/cli.js +10028 -8119
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,149 @@ read-only in every version below.
|
|
|
7
7
|
GitHub already has release pages for [v0.1.0](https://github.com/SimaAlexandru99/agentscan/releases/tag/v0.1.0)
|
|
8
8
|
and [v0.4.0](https://github.com/SimaAlexandru99/agentscan/releases/tag/v0.4.0).
|
|
9
9
|
0.9.0 was planned as a separate train and shipped inside 1.0.0.
|
|
10
|
+
1.0.1 is the shared-MCP hotfix; it is documented below and ships inside 1.1.0
|
|
11
|
+
(the published package version). A separate 1.0.1 npm tag would need an
|
|
12
|
+
intermediate commit that this train does not cut.
|
|
13
|
+
|
|
14
|
+
## 1.1.0 — 2026-08-31
|
|
15
|
+
|
|
16
|
+
Native Command Code provider, then a correctness pass over every registered
|
|
17
|
+
check against 2026-08-31 official docs. Includes 1.0.1. **87 checks**, **420
|
|
18
|
+
tests**.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Hook schema profiles: `claude` | `vscode-native` | `copilot-cli` |
|
|
23
|
+
`commandcode`. `.github/hooks` with `version: 1` is Copilot CLI.
|
|
24
|
+
- Claude hook schema: required `type` (not inferred from `command`/`url`);
|
|
25
|
+
`mcp_tool` needs `server` + `tool`; `prompt`/`agent` need `prompt`;
|
|
26
|
+
documented event/handler compatibility; nested matcher groups only.
|
|
27
|
+
- Copilot CLI: camelCase events mapped onto VS Code names; `bash` /
|
|
28
|
+
`powershell` / `command`; `cwd`; `timeoutSec` then `timeout`. Prompt
|
|
29
|
+
hooks only on `sessionStart`. User `~/.copilot/hooks` under `--global`.
|
|
30
|
+
- Agent Skills optional constrained fields: `compatibility` 1..500,
|
|
31
|
+
`metadata` map<string,string>, `allowed-tools` string. Info for
|
|
32
|
+
`SKILL.md` >500 lines. File references resolve from the skill root only.
|
|
33
|
+
- Claude skill listing budget: 1% context window, 8000-character fallback,
|
|
34
|
+
per-entry cap 1536, listing text is description (or first markdown
|
|
35
|
+
paragraph) plus `when_to_use`. First paragraph satisfies missing
|
|
36
|
+
description.
|
|
37
|
+
- OpenCode V2: local `command` must be an argv array
|
|
38
|
+
(`opencode.mcp.command-not-array`).
|
|
39
|
+
- Continue standalone YAML blocks require `name` / `version` / `schema`
|
|
40
|
+
(`continue.mcp.missing-block-metadata`). Copied JSON is not checked.
|
|
41
|
+
- Gemini underscore alias warning (`gemini.mcp.underscore-alias`).
|
|
42
|
+
- Claude reserved MCP names including `workspace`
|
|
43
|
+
(`claude.mcp.reserved-name`).
|
|
44
|
+
- Codex chain knobs: `AGENTS.override.md` > `AGENTS.md` >
|
|
45
|
+
`project_doc_fallback_filenames`; one file per directory; root→cwd;
|
|
46
|
+
`project_doc_max_bytes`; `project_root_markers`.
|
|
47
|
+
- Coverage matrix uses five dimensions (project discovery, global
|
|
48
|
+
discovery, schema, precedence, conformance) instead of `full` /
|
|
49
|
+
`partial`.
|
|
50
|
+
- Conformance fixture `tests/fixtures/conformance/copilot-hooks/`.
|
|
51
|
+
- Spec capture `docs/spec/copilot-hooks.md`. Alias
|
|
52
|
+
`claude.hook.mcp-tool-without-name` →
|
|
53
|
+
`claude.hook.mcp-tool-without-server-or-tool`.
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- Nested `<dir>/.commandcode/AGENTS.md` is Command Code memory when that
|
|
58
|
+
directory has no `AGENTS.md` (official memory table).
|
|
59
|
+
- Native VS Code remains command-only with its documented eight events.
|
|
60
|
+
`vscode.hook.http-without-url` and `vscode.hook.mcp-tool-without-name`
|
|
61
|
+
are removed.
|
|
62
|
+
- Claude agent names: lowercase letters and hyphens (no digits); filename
|
|
63
|
+
is not compared to `name`.
|
|
64
|
+
- `skill.description-budget` provenance is vendor-recommendation, not a
|
|
65
|
+
16000-byte heuristic.
|
|
66
|
+
|
|
67
|
+
### Added (Command Code provider)
|
|
68
|
+
|
|
69
|
+
- Provider `commandcode` from official pages under `docs/spec/commandcode-*.md`
|
|
70
|
+
(read 2026-08-31). Unknown stays skip: no invented local-project MCP slug,
|
|
71
|
+
no bundled-skill scan, no `--skill` flags, no model-id list, no mods
|
|
72
|
+
execution.
|
|
73
|
+
- Skills: `.commandcode/skills` only at the Command Code project root
|
|
74
|
+
(Agent Skills contract), `.agents/skills` walk-up (max 10 hops from cwd,
|
|
75
|
+
stopping at home), extra dirs from the highest-precedence settings
|
|
76
|
+
`skills` array (replace, not merge; relative paths resolve against the git
|
|
77
|
+
root). User `~/.commandcode/skills` and `~/.agents/skills` under
|
|
78
|
+
`--global`.
|
|
79
|
+
- Memory: per directory, first existing of `AGENTS.md` or
|
|
80
|
+
`.commandcode/AGENTS.md` (project and nested). User
|
|
81
|
+
`~/.commandcode/AGENTS.md` under `--global`. Unresolved `@path` is not a
|
|
82
|
+
hard error. Codex's instruction chain excludes `.commandcode/AGENTS.md`.
|
|
83
|
+
- Agents: `<project>/.commandcode/agents/*.md` at the Command Code project
|
|
84
|
+
root only (git root, or cwd outside a git repo); filename supplies
|
|
85
|
+
`name`; no `claude.agent.*` on these files. Checks:
|
|
86
|
+
`commandcode.agent.reserved-name` (`explore` / `plan` / `review` /
|
|
87
|
+
`general`), `invalid-permission-mode`, `invalid-field-type` covering every
|
|
88
|
+
documented custom-agent typed field (`reasoningEffort` is not one of them).
|
|
89
|
+
`maxTurns` must be a positive integer.
|
|
90
|
+
- Hooks: four events (`PreToolUse`, `PostToolUse`, `Stop`, `SessionStart`);
|
|
91
|
+
nested `hooks` array required; `type` must be the string `"command"`;
|
|
92
|
+
`command` must be a string (not an argv array); `matcher` must be a string
|
|
93
|
+
when present. Timeout 0–600. A matcher on `Stop` / `SessionStart` is
|
|
94
|
+
runtime-dead, not a schema error. Project and user hooks for the same event
|
|
95
|
+
coexist; only an exact duplicate command string is deduplicated (project
|
|
96
|
+
wins). `settings.local.json` follows settings merge (an event array
|
|
97
|
+
replaces the project array for that event). `COMMANDCODE_PROJECT_DIR` and
|
|
98
|
+
`COMMANDCODE_CWD` expand against the Command Code project root.
|
|
99
|
+
- Settings: Command Code project root is the git root (a child `.cursor`
|
|
100
|
+
does not hide `<git-root>/.commandcode/`). `model` inventoried, not
|
|
101
|
+
validated. Inline `mcp.servers` (array or object map; unnamed array items
|
|
102
|
+
are inventory-only). User `~/.commandcode/mcp.json` under `--global`.
|
|
103
|
+
Spec/runtime checks skip shadowed lower-precedence definitions; security
|
|
104
|
+
checks still inspect every readable MCP file.
|
|
105
|
+
- Slash commands: inventory `.commandcode/commands` at the project root and
|
|
106
|
+
the user dir — no required-field checks.
|
|
107
|
+
- Mods: inventory `mods.paths` — never execute or import TypeScript.
|
|
108
|
+
- Conformance fixture `tests/fixtures/conformance/commandcode/`.
|
|
109
|
+
- `spec:check` tracks captured surfaces and diffs Claude, VS Code, Copilot
|
|
110
|
+
CLI, and Command Code hook events against live pages.
|
|
111
|
+
|
|
112
|
+
### Also changed
|
|
113
|
+
|
|
114
|
+
- Default `skillPaths` includes `.commandcode/skills`.
|
|
115
|
+
- `--global` / `includeGlobal` also scans `~/.commandcode/skills`,
|
|
116
|
+
`~/.agents/skills`, user Command Code agents, MCP, memory, Copilot user
|
|
117
|
+
hooks, and Codex global AGENTS files.
|
|
118
|
+
- Shared `.mcp.json` is `mcp-json`, not Claude-only.
|
|
119
|
+
|
|
120
|
+
## 1.0.1 — 2026-08-31
|
|
121
|
+
|
|
122
|
+
Shared `.mcp.json` is not Claude-only. Command Code writes it for `--scope
|
|
123
|
+
project` with `transport` (and `type` as an alias). A Claude-keyed
|
|
124
|
+
`url`-without-`type` check on that path is a false positive on valid
|
|
125
|
+
Command Code HTTP config.
|
|
126
|
+
|
|
127
|
+
### Fixed
|
|
128
|
+
|
|
129
|
+
- `.mcp.json` uses schema profile `mcp-json`, `consumedBy: ["claude",
|
|
130
|
+
"commandcode"]`, `sourceProvider: "unknown"`. `.claude/mcp.json` and
|
|
131
|
+
project `mcp.json` stay `claude-json`.
|
|
132
|
+
- Parse `transport` first; `type` is an alias. Store which field was
|
|
133
|
+
present.
|
|
134
|
+
- `claude.mcp.url-without-type` on `mcp-json` fires only when `url` is set
|
|
135
|
+
and transport is unset. On `claude-json` it still fires when the field is
|
|
136
|
+
`transport` or missing. `{ "transport": "http", "url": "…" }` does not
|
|
137
|
+
emit this.
|
|
138
|
+
- Command Code transport defects on `mcp-json` and `commandcode-json`:
|
|
139
|
+
`commandcode.mcp.invalid-transport`, `http-without-url`,
|
|
140
|
+
`stdio-without-command`. Valid transports are `http` and `stdio`. Claude
|
|
141
|
+
`sse` / `ws` on shared `.mcp.json` is not a Command Code invalid-transport.
|
|
142
|
+
- Empty launch on `mcp-json` still emits `claude.mcp.no-launch` (both
|
|
143
|
+
consumers need a launch field). `commandcode-json` empty launch emits
|
|
144
|
+
`commandcode.mcp.no-launch`.
|
|
145
|
+
- `looksLikeServerEntry` recognises `transport`. Absolute MCP paths under
|
|
146
|
+
`--global` are not joined as relative.
|
|
147
|
+
|
|
148
|
+
### Security
|
|
149
|
+
|
|
150
|
+
- Never open `~/.commandcode/auth.json` or `mcp-tokens.json`.
|
|
151
|
+
- Local `~/.commandcode/projects/{project}/mcp.json` is unread: the slug
|
|
152
|
+
encoding is unpublished. Prefer skip over inventing it.
|
|
10
153
|
|
|
11
154
|
## 1.0.0 — 2026-08-30
|
|
12
155
|
|
package/README.md
CHANGED
|
@@ -5,19 +5,19 @@
|
|
|
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-87-111111?style=flat-square" alt="87 checks">
|
|
9
|
+
<img src="https://img.shields.io/badge/tests-420%20passing-111111?style=flat-square" alt="420 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">
|
|
13
13
|
<img src="https://img.shields.io/npm/v/@chimix/agentscan?style=flat-square&color=111111&label=npm" alt="npm version">
|
|
14
14
|
<img src="https://img.shields.io/badge/license-MIT-111111?style=flat-square" alt="MIT license">
|
|
15
|
-
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/changelog-1.
|
|
15
|
+
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/changelog-1.1.0-111111?style=flat-square" alt="Changelog"></a>
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
19
|
-
<strong>
|
|
20
|
-
<sub>An offline linter for Claude Code, portable Agent Skills, nested AGENTS.md, and the MCP / hooks / rules surfaces that 1.
|
|
19
|
+
<strong>87 checks · offline · 0 network calls on <code>check</code> · provenance on every rule</strong><br>
|
|
20
|
+
<sub>An offline linter for Claude Code, Command Code, portable Agent Skills, nested AGENTS.md, Copilot CLI hooks, and the MCP / hooks / rules surfaces that 1.1.0 actually implements. Spec-required checks cite a published line in <a href="docs/spec/">docs/spec/</a>. Heuristics stay at <code>info</code> and say so. The coverage matrix below is the honesty contract — five dimensions, and a documented global location that is not scanned stays unread.</sub>
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
23
|
---
|
|
@@ -63,9 +63,9 @@ of the filesystem**, where nothing else in your stack will ever tell you.
|
|
|
63
63
|
No AI, no network on `check`. Read the config, read the disk, compare:
|
|
64
64
|
|
|
65
65
|
```
|
|
66
|
-
1. Discover .claude/ .agents/ .vscode/ .cursor/ .codex/ .gemini/ .github/ .continue/ AGENTS.md skills-lock.json
|
|
66
|
+
1. Discover .claude/ .commandcode/ .agents/ .vscode/ .cursor/ .codex/ .gemini/ .github/ .continue/ AGENTS.md skills-lock.json
|
|
67
67
|
2. Extract immutable facts — never re-read during checking
|
|
68
|
-
3. Check
|
|
68
|
+
3. Check 87 checks, each labeled spec-required, vendor-recommendation,
|
|
69
69
|
security, internal-consistency, or heuristic
|
|
70
70
|
4. Report text · --json · --output prompt (handoff for a fixing agent)
|
|
71
71
|
```
|
|
@@ -116,10 +116,10 @@ too close to an unrelated `agent-scan`. The command you type stays `agentscan`.
|
|
|
116
116
|
bun add -d @chimix/agentscan # then: bunx agentscan check
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
Point it at a project that actually has agent config — a `.claude/`
|
|
120
|
-
an `.mcp.json`, an `AGENTS.md`. A directory with
|
|
121
|
-
`package.json` is still scannable. On a directory with
|
|
122
|
-
clear error.
|
|
119
|
+
Point it at a project that actually has agent config — a `.claude/` or
|
|
120
|
+
`.commandcode/` directory, an `.mcp.json`, an `AGENTS.md`. A directory with
|
|
121
|
+
agent config and no `package.json` is still scannable. On a directory with
|
|
122
|
+
neither it exits with a clear error.
|
|
123
123
|
|
|
124
124
|
```bash
|
|
125
125
|
# what it could possibly report, before you run it
|
|
@@ -186,7 +186,7 @@ Flags for `check`:
|
|
|
186
186
|
| `--verbose` | Show KEEP + info-severity findings, and print each finding's id |
|
|
187
187
|
| `--fail-on <level>` | `never` (default) · `warning` · `error` |
|
|
188
188
|
| `--fail-under <0-100>` | Fail when the score drops below this floor |
|
|
189
|
-
| `--global` | Also scan `~/.claude/skills
|
|
189
|
+
| `--global` | Also scan `~/.claude/skills`, `~/.codex/skills`, `~/.commandcode/skills`, and `~/.agents/skills` (see below) |
|
|
190
190
|
| `--config <path>` | Config file path |
|
|
191
191
|
|
|
192
192
|
**v1 does not write the tree** — no `apply`, no skill delete/install. Findings may *suggest* shell commands; you run them yourself.
|
|
@@ -199,7 +199,7 @@ Flags for `check`:
|
|
|
199
199
|
│ ⌒ │ 6 error · 2 warning · 11 info hidden (--verbose)
|
|
200
200
|
└─────┘
|
|
201
201
|
|
|
202
|
-
agentscan v1.
|
|
202
|
+
agentscan v1.1.0 — touchagency
|
|
203
203
|
|
|
204
204
|
Scanned: 46 deps · 108 skills · 1 mcp · 2 agents · packageManager=bun
|
|
205
205
|
|
|
@@ -231,7 +231,7 @@ JSON shape (abridged):
|
|
|
231
231
|
|
|
232
232
|
```json
|
|
233
233
|
{
|
|
234
|
-
"version": "1.
|
|
234
|
+
"version": "1.1.0",
|
|
235
235
|
"root": "/path/to/project",
|
|
236
236
|
"factsSummary": {
|
|
237
237
|
"packageManager": "bun",
|
|
@@ -259,10 +259,14 @@ Same tree → same sorted findings, with stable unique `id`s.
|
|
|
259
259
|
|
|
260
260
|
### `--global`
|
|
261
261
|
|
|
262
|
-
Adds `~/.claude/skills
|
|
263
|
-
`SKILL.md` that is malformed is
|
|
264
|
-
carry a `source: global`
|
|
265
|
-
|
|
262
|
+
Adds `~/.claude/skills`, `~/.codex/skills`, `~/.commandcode/skills`, and
|
|
263
|
+
`~/.agents/skills` to the structural checks: a `SKILL.md` that is malformed is
|
|
264
|
+
malformed wherever it lives, and those findings carry a `source: global`
|
|
265
|
+
evidence entry so you can tell them apart. Codex and Command Code skills use
|
|
266
|
+
the Agent Skills contract (`name` and `description` required). `--global` also
|
|
267
|
+
inventories user Command Code agents (`~/.commandcode/agents`), MCP
|
|
268
|
+
(`~/.commandcode/mcp.json` and user settings `mcp.servers`), and memory
|
|
269
|
+
(`~/.commandcode/AGENTS.md`). It never opens `auth.json` or `mcp-tokens.json`.
|
|
266
270
|
|
|
267
271
|
Lockfile checks stay project-scoped — a project lockfile cannot pin a skill that
|
|
268
272
|
lives in your home directory, so reporting one as "not in the lockfile" could
|
|
@@ -342,8 +346,8 @@ Optional `.agentscanrc.json` (create with `agentscan init`):
|
|
|
342
346
|
|
|
343
347
|
```json
|
|
344
348
|
{
|
|
345
|
-
"skillPaths": [".agents/skills", ".claude/skills", "skills", ".cursor/skills", ".codex/skills"],
|
|
346
|
-
"mcpPaths": [".mcp.json", ".claude/mcp.json", "mcp.json", ".vscode/mcp.json", ".cursor/mcp.json", ".agents/mcp_config.json", ".codex/config.toml"],
|
|
349
|
+
"skillPaths": [".agents/skills", ".claude/skills", "skills", ".cursor/skills", ".codex/skills", ".commandcode/skills"],
|
|
350
|
+
"mcpPaths": [".mcp.json", ".claude/mcp.json", "mcp.json", ".vscode/mcp.json", ".cursor/mcp.json", ".agents/mcp_config.json", ".codex/config.toml", ".gemini/settings.json", "opencode.json", "opencode.jsonc", ".opencode/opencode.json", ".opencode/opencode.jsonc", ".continue/config.yaml", ".continue/mcpServers"],
|
|
347
351
|
"policyFiles": ["AGENTS.md", "CLAUDE.md"],
|
|
348
352
|
"ignoreSkills": [],
|
|
349
353
|
"ignoreRules": [],
|
|
@@ -352,8 +356,8 @@ Optional `.agentscanrc.json` (create with `agentscan init`):
|
|
|
352
356
|
"includeGlobal": false,
|
|
353
357
|
"requireLock": false,
|
|
354
358
|
"thresholds": {
|
|
355
|
-
"
|
|
356
|
-
"
|
|
359
|
+
"skillListingChars": 8000,
|
|
360
|
+
"skillListingMaxDescChars": 1536,
|
|
357
361
|
"mcp": 5,
|
|
358
362
|
"agentsMdLines": 150,
|
|
359
363
|
"claudeMdLines": 200,
|
|
@@ -434,29 +438,61 @@ internal-consistency, or heuristic. `agentscan rules` lists them all.
|
|
|
434
438
|
| `claude.agent.missing-frontmatter` | error | A Claude agent definition with no `---` block |
|
|
435
439
|
| `claude.agent.missing-description` | error | Claude agent frontmatter has no `description` |
|
|
436
440
|
| `claude.agent.missing-name` | error | Claude agent frontmatter has no `name` |
|
|
437
|
-
| `claude.agent.invalid-name` | warning | Claude agent name is not lowercase letters
|
|
441
|
+
| `claude.agent.invalid-name` | warning | Claude agent name is not lowercase letters and hyphens (error if it starts with `-` or contains `:`; filename is not compared) |
|
|
438
442
|
| `claude.agent.duplicate-name` | error | Multiple Claude agent files declare the same name |
|
|
439
443
|
| `claude.mcp.no-launch` | error | A Claude MCP server with neither `command` nor `url` |
|
|
440
|
-
| `claude.mcp.url-without-type` | error | A Claude remote MCP server with a `url` but no `type` — read as stdio and skipped |
|
|
444
|
+
| `claude.mcp.url-without-type` | error | A Claude remote MCP server with a `url` but no `type` — read as stdio and skipped. On shared `.mcp.json`, a Command Code `transport` field satisfies the other consumer and this check does not fire |
|
|
445
|
+
| `claude.mcp.reserved-name` | error | A Claude-consumed MCP server named with a reserved identifier (`workspace`, `claude-in-chrome`, `computer-use`, `Claude Preview`, `Claude Browser`) — skipped at load |
|
|
441
446
|
| `vscode.mcp.no-launch` | error | A VS Code MCP server (`servers`) with neither `command` nor `url` |
|
|
442
447
|
| `cursor.mcp.no-launch` | error | A Cursor MCP server with neither `command` nor `url` |
|
|
443
448
|
| `antigravity.mcp.no-launch` | error | An Antigravity MCP server with neither `command` nor `serverUrl` |
|
|
444
449
|
| `codex.mcp.no-launch` | error | A Codex `[mcp_servers.*]` entry with neither `command` nor `url` |
|
|
445
450
|
| `gemini.mcp.no-launch` | error | A Gemini MCP server with neither `command`, `url`, nor `httpUrl` |
|
|
451
|
+
| `gemini.mcp.underscore-alias` | warning | A Gemini MCP server alias contains `_`, which can make policies fail silently |
|
|
446
452
|
| `opencode.mcp.no-launch` | error | An OpenCode MCP server with neither `command` nor `url` |
|
|
447
453
|
| `opencode.mcp.missing-type` | error | An OpenCode MCP server missing `type: local` or `type: remote` |
|
|
448
454
|
| `opencode.mcp.local-without-command` | error | An OpenCode `type: local` server with no `command` |
|
|
449
455
|
| `opencode.mcp.remote-without-url` | error | An OpenCode `type: remote` server with no `url` |
|
|
450
456
|
| `opencode.mcp.invalid-launch-for-type` | error | An OpenCode server whose launch field does not match its `type` |
|
|
457
|
+
| `opencode.mcp.command-not-array` | error | An OpenCode V2 local `command` that is not an argv array |
|
|
451
458
|
| `continue.mcp.no-launch` | error | A Continue MCP server with neither `command`, `url`, nor `uses` |
|
|
459
|
+
| `continue.mcp.missing-block-metadata` | error | A standalone `.continue/mcpServers/*.yaml` block missing `name`, `version`, or `schema` (not applied to copied JSON) |
|
|
460
|
+
| `commandcode.mcp.no-launch` | error | A Command Code settings / user MCP server with neither `command` nor `url` |
|
|
461
|
+
| `commandcode.mcp.invalid-transport` | error | A Command Code MCP `transport` / `type` that is not `http` or `stdio` (Claude `sse` / `ws` on shared `.mcp.json` is skipped) |
|
|
462
|
+
| `commandcode.mcp.http-without-url` | error | A Command Code HTTP MCP server with no `url` |
|
|
463
|
+
| `commandcode.mcp.stdio-without-command` | error | A Command Code stdio MCP server with no `command` |
|
|
452
464
|
| `claude.hook.command-without-command` | error | A Claude `type: command` hook with no `command` |
|
|
453
|
-
| `claude.hook.
|
|
465
|
+
| `claude.hook.http-without-url` | error | A Claude `type: http` hook with no `url` |
|
|
466
|
+
| `claude.hook.mcp-tool-without-server-or-tool` | error | A Claude `type: mcp_tool` hook missing `server` or `tool` |
|
|
467
|
+
| `claude.hook.unknown-handler-type` | error | A Claude hook whose required `type` is missing or not one of command, http, mcp_tool, prompt, agent |
|
|
468
|
+
| `claude.hook.prompt-without-prompt` | error | A Claude `type: prompt` or `type: agent` hook with no `prompt` |
|
|
469
|
+
| `claude.hook.incompatible-handler` | error | A Claude handler type that the event does not support |
|
|
470
|
+
| `claude.hook.invalid-group` | error | A Claude hook matcher group with no nested `hooks` array (flat handler arrays are invalid) |
|
|
471
|
+
| `vscode.hook.invalid-group` | error | A VS Code hook group that is not a command handler array |
|
|
472
|
+
| `vscode.hook.command-without-command` | error | A native VS Code `type: command` hook with no `command` |
|
|
473
|
+
| `vscode.hook.unknown-handler-type` | error | A native VS Code hook whose `type` is not `command` |
|
|
474
|
+
| `copilot.hook.unknown-event` | error | A Copilot CLI hook registered under an event that is never dispatched |
|
|
475
|
+
| `copilot.hook.missing-script` | error | A Copilot CLI command hook whose script does not exist |
|
|
476
|
+
| `copilot.hook.command-without-command` | error | A Copilot CLI command hook with none of `bash`, `powershell`, or `command` |
|
|
477
|
+
| `copilot.hook.http-without-url` | error | A Copilot CLI `type: http` hook with no `url` |
|
|
478
|
+
| `copilot.hook.prompt-without-prompt` | error | A Copilot CLI `type: prompt` hook with no `prompt` |
|
|
479
|
+
| `copilot.hook.unknown-handler-type` | error | A Copilot CLI hook whose `type` is not command, http, or prompt |
|
|
480
|
+
| `copilot.hook.incompatible-handler` | error | A Copilot CLI prompt hook registered on an event other than `sessionStart` |
|
|
481
|
+
| `commandcode.hook.unknown-event` | error | A Command Code hook registered under an event that is never dispatched (four events only) |
|
|
482
|
+
| `commandcode.hook.missing-script` | error | A Command Code command hook whose script does not exist |
|
|
483
|
+
| `commandcode.hook.invalid-group` | error | A Command Code hook group missing the required nested `hooks` array, or a non-string `matcher` |
|
|
484
|
+
| `commandcode.hook.command-without-command` | error | A Command Code `type: command` hook whose `command` is missing, empty, or not a string |
|
|
485
|
+
| `commandcode.hook.unknown-handler-type` | error | A Command Code hook whose `type` is missing, not a string, or not `"command"` |
|
|
486
|
+
| `commandcode.hook.timeout-out-of-bounds` | error | A Command Code hook `timeout` outside 0–600 seconds |
|
|
487
|
+
| `commandcode.agent.reserved-name` | error | A Command Code custom agent named `explore`, `plan`, `review`, or `general` — ignored at load |
|
|
488
|
+
| `commandcode.agent.invalid-permission-mode` | error | A Command Code agent `permissionMode` that is not a documented value |
|
|
489
|
+
| `commandcode.agent.invalid-field-type` | error | A Command Code agent field whose type the spec does not accept |
|
|
454
490
|
| `mcp.command-missing` | error | An MCP `command` that is a path-like value whose file does not exist on disk |
|
|
455
491
|
| `security.hardcoded-secret` | error | A token-shaped literal in MCP config (the value is never echoed back) |
|
|
456
492
|
| `mcp.literal-env` | warning | Secret-named `env` values that are literals instead of interpolation |
|
|
457
493
|
| `skill.missing-skill-md` | warning | A directory under a skill path with no `SKILL.md` |
|
|
458
494
|
| `claude.skill.missing-frontmatter` | warning | Claude `SKILL.md` with no `---` block |
|
|
459
|
-
| `claude.skill.missing-description` | info | Claude frontmatter has no `description`
|
|
495
|
+
| `claude.skill.missing-description` | info | Claude frontmatter has no `description` and no first markdown paragraph |
|
|
460
496
|
| `agent-skills.skill.missing-frontmatter` | error | Portable skill `SKILL.md` has no YAML frontmatter |
|
|
461
497
|
| `agent-skills.skill.missing-name` | error | Portable skill frontmatter has no required `name` |
|
|
462
498
|
| `agent-skills.skill.missing-description` | error | Portable skill frontmatter has no required `description` |
|
|
@@ -464,11 +500,15 @@ internal-consistency, or heuristic. `agentscan rules` lists them all.
|
|
|
464
500
|
| `agent-skills.skill.name-does-not-match-directory` | error | Portable skill `name` does not match its directory |
|
|
465
501
|
| `agent-skills.skill.name-too-long` | error | Portable skill name exceeds 64 characters |
|
|
466
502
|
| `agent-skills.skill.description-too-long` | error | Portable skill description exceeds 1024 characters |
|
|
503
|
+
| `agent-skills.skill.invalid-compatibility` | error | Portable skill `compatibility` is present but is not a 1–500 character string |
|
|
504
|
+
| `agent-skills.skill.invalid-metadata` | error | Portable skill `metadata` is present but is not `map<string, string>` |
|
|
505
|
+
| `agent-skills.skill.invalid-allowed-tools` | error | Portable skill `allowed-tools` is present but is not a string |
|
|
506
|
+
| `agent-skills.skill.body-too-large` | info | Portable skill `SKILL.md` exceeds the 500-line recommendation |
|
|
467
507
|
| `skill.broken-reference` | warning | The body points at a bundled file that does not exist |
|
|
468
508
|
| `skill.duplicate-description` | info | Two or more skills carry an identical description (heuristic) |
|
|
469
509
|
| `skill.locked-not-installed` | warning | `skills-lock.json` pins a skill that is not on disk |
|
|
470
510
|
| `skill.not-in-lock` | info | A skill on disk that the lockfile does not track (installer policy) |
|
|
471
|
-
| `skill.description-budget` | info | Claude skill
|
|
511
|
+
| `skill.description-budget` | info | Claude skill listing text (description or first paragraph, plus `when_to_use`) exceeds the 1% context-window budget, with an 8000-character fallback and a 1536-character per-entry cap |
|
|
472
512
|
| `skill.no-lockfile` | info | Skills present with no lockfile at all (only with `requireLock`) |
|
|
473
513
|
| `budget.agents-md` | info | `AGENTS.md` past a secondary 150-line hint (heuristic; not an AGENTS.md requirement) |
|
|
474
514
|
| `budget.claude-md` | info | `CLAUDE.md` past the official “target under 200 lines” recommendation |
|
|
@@ -477,44 +517,57 @@ internal-consistency, or heuristic. `agentscan rules` lists them all.
|
|
|
477
517
|
| `codex.budget.instructions` | info | Codex root→cwd `AGENTS.md` chain exceeds the default 32 KiB |
|
|
478
518
|
| `cursor.rule.too-large` | info | A `.cursor/rules/*.mdc` file exceeds the 500-line recommendation |
|
|
479
519
|
|
|
480
|
-
### Coverage in 1.
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
|
494
|
-
|
|
495
|
-
|
|
|
496
|
-
|
|
|
497
|
-
|
|
|
498
|
-
|
|
|
499
|
-
|
|
|
500
|
-
|
|
|
501
|
-
|
|
|
502
|
-
|
|
|
520
|
+
### Coverage in 1.1.0
|
|
521
|
+
|
|
522
|
+
Each cell is one coverage dimension. There is no `full` / `partial` label: a
|
|
523
|
+
documented global or static location that is not opened stays **unread**.
|
|
524
|
+
|
|
525
|
+
Dimensions:
|
|
526
|
+
|
|
527
|
+
- **project discovery** — documented in-repo files the scanner opens
|
|
528
|
+
- **global discovery** — documented user / machine locations; `--global` is named when that is the only path that opens them
|
|
529
|
+
- **schema** — spec-required (and labeled vendor-recommendation) field checks
|
|
530
|
+
- **precedence** — documented merge / override / shadowing
|
|
531
|
+
- **conformance** — official-shaped fixture or equivalent negative tests
|
|
532
|
+
|
|
533
|
+
| Ecosystem | project discovery | global discovery | schema | precedence | conformance |
|
|
534
|
+
|-----------|-------------------|------------------|--------|------------|-------------|
|
|
535
|
+
| Agent Skills | `.agents/skills` (and Cursor / Codex / Command Code skill trees) | `--global` `~/.agents/skills`, `~/.codex/skills` | required `name` / `description` plus optional `compatibility` / `metadata` / `allowed-tools`; 500-line info | n/a | `agent-skills` fixture |
|
|
536
|
+
| AGENTS.md | nested walk-up | n/a | no required fields | nearest-wins | tests |
|
|
537
|
+
| Claude Code | project settings, skills, agents, `CLAUDE.md`, `.mcp.json` / `.claude/mcp.json` | unread `~/.claude/settings.json`, managed policy, marketplace plugins | 33 events; required handler `type`; MCP reserved names; first-paragraph skill description; listing budget | walk-up `CLAUDE.md` / `.claude/agents` | `claude-json` fixture |
|
|
538
|
+
| Command Code | git-root project files; per-directory `AGENTS.md` else `.commandcode/AGENTS.md` | `--global` `~/.commandcode/*`; unread `projects/{slug}/mcp.json` | 4 events; command handlers; Agent Skills; MCP `transport` / `type` | settings merge; project+user hooks coexist; skill/MCP shadow | `commandcode` fixture |
|
|
539
|
+
| Codex | `.codex/config.toml`, `.codex/skills`, AGENTS chain | `--global` `~/.codex/AGENTS.override.md` then `AGENTS.md` | TOML MCP; `project_doc_max_bytes`; Agent Skills | override > `AGENTS.md` > fallbacks; one file per dir; root→cwd; `project_root_markers` | `codex-toml` fixture |
|
|
540
|
+
| VS Code | `.github/hooks` without `version: 1`, instruction files, `.github/agents`, `.vscode/mcp.json` | `--global` `~/.copilot/hooks` without `version: 1`; unread policy dirs | 8 events; command-only | workspace over user | `vscode-hooks`, `vscode-json` |
|
|
541
|
+
| Copilot CLI | `.github/hooks` with `version: 1` | `--global` `~/.copilot/hooks` with `version: 1`; unread `/etc/github-copilot/policy.d` | camelCase + PascalCase map; `bash` / `powershell` / `command`; `cwd`; `timeoutSec`; prompt on `sessionStart` | documented sources coexist; policy unread | `copilot-hooks` fixture |
|
|
542
|
+
| Cursor | nested `.cursor/skills`, `.cursor/mcp.json`, `.cursor/rules` | unread documented Cursor user/global paths | Agent Skills; MCP launch; 500-line rules | n/a | `cursor-json` fixture |
|
|
543
|
+
| Grok | none | none | none | n/a | none |
|
|
544
|
+
| Antigravity | `.agents/mcp_config.json` | none | `serverUrl` launch | n/a | `antigravity-json` fixture |
|
|
545
|
+
| Gemini | `.gemini/settings.json` | unread `~/.gemini/settings.json` unless `--global` is wired for it (it is not) | `command` / `url` / `httpUrl`; underscore-alias warning | n/a | `gemini-json` fixture |
|
|
546
|
+
| Windsurf | none | unread (official page is global-only) | none | n/a | none |
|
|
547
|
+
| Kiro | none | none | none | n/a | none |
|
|
548
|
+
| Cline | none | none | none | n/a | none |
|
|
549
|
+
| Roo | none | none | none | n/a | none |
|
|
550
|
+
| Kilo | none | none | none | n/a | none |
|
|
551
|
+
| OpenCode | `opencode.json(c)` V1 and V2 | none | V2 local `command` must be an argv array | n/a | `opencode-json` fixture |
|
|
552
|
+
| Junie | none | none | none | n/a | none |
|
|
553
|
+
| Continue | `.continue/config.yaml`, `.continue/mcpServers/*` | none | launch `command` / `url` / `uses`; standalone YAML `name` / `version` / `schema` | n/a | `continue-yaml`, `continue-mcpservers` |
|
|
503
554
|
|
|
504
555
|
Cursor project rules (`.cursor/rules/**/*.mdc`) are a separate surface: discovery plus `cursor.rule.too-large` at info. Claude `.claude/rules/**/*.md` is inventoried and has no published line budget.
|
|
505
556
|
|
|
506
557
|
Old 0.7 rule ids still work in `ignoreRules` and `explain` (for example `hook.missing-script` aliases `claude.hook.missing-script`).
|
|
507
558
|
|
|
508
|
-
Agent definitions are checked for structure only.
|
|
509
|
-
is not compared to the filename; it must
|
|
510
|
-
and unique.
|
|
511
|
-
|
|
512
|
-
|
|
559
|
+
Agent definitions are checked for structure only. A Claude agent's frontmatter
|
|
560
|
+
`name` is not compared to the filename; it must be lowercase letters and
|
|
561
|
+
hyphens and unique. Command Code supplies `name` from the filename when
|
|
562
|
+
frontmatter omits it, and does not emit missing-name or missing-description.
|
|
563
|
+
Model identifiers and tool names are likewise not validated: both would need a
|
|
564
|
+
hardcoded list, which is the shape that already shipped a false error. See
|
|
565
|
+
[plans/003](plans/003-validate-agent-definitions.md).
|
|
513
566
|
|
|
514
567
|
`skill.broken-reference` reads the body, not just the frontmatter. It looks for
|
|
515
568
|
paths under the conventional bundled directories (`scripts/`, `references/`,
|
|
516
|
-
`assets/`, `templates/`, `examples/`)
|
|
517
|
-
|
|
569
|
+
`assets/`, `templates/`, `examples/`). Agent Skills references resolve from the
|
|
570
|
+
skill root only. Claude native skills also try the repo root — of 1674
|
|
518
571
|
references measured across 17 projects, 1645 resolved skill-relative and 12 only
|
|
519
572
|
at the root. Fenced code blocks are stripped first: a path in an example is
|
|
520
573
|
illustration, not a pointer.
|
|
@@ -522,7 +575,8 @@ illustration, not a pointer.
|
|
|
522
575
|
### Where it looks for hooks
|
|
523
576
|
|
|
524
577
|
The Claude hooks reference lists seven places a hook can be registered. agentscan
|
|
525
|
-
reads the four that live inside the scanned project, plus VS Code workspace hooks
|
|
578
|
+
reads the four that live inside the scanned project, plus VS Code workspace hooks
|
|
579
|
+
and Command Code settings hooks:
|
|
526
580
|
|
|
527
581
|
| Registered in | Script paths resolve against |
|
|
528
582
|
|---|---|
|
|
@@ -530,7 +584,10 @@ reads the four that live inside the scanned project, plus VS Code workspace hook
|
|
|
530
584
|
| A plugin's `hooks/hooks.json` (a directory with `.claude-plugin/plugin.json`, or the scan root itself) | the plugin root, `${CLAUDE_PLUGIN_ROOT}` |
|
|
531
585
|
| `SKILL.md` frontmatter | the skill's own directory, then the project root |
|
|
532
586
|
| `.claude/agents/*.md` frontmatter | the agent file's directory, then the project root |
|
|
533
|
-
| `.github/hooks/*.json` (VS Code) | project root and the hooks directory |
|
|
587
|
+
| `.github/hooks/*.json` without `version: 1` (native VS Code) | project root and the hooks directory |
|
|
588
|
+
| `.github/hooks/*.json` with `version: 1` (Copilot CLI) | project root, `cwd`, host `bash` / `powershell` / `command` |
|
|
589
|
+
| `~/.copilot/hooks` under `--global` | same split on `version: 1` |
|
|
590
|
+
| `.commandcode/settings.json` · `.commandcode/settings.local.json` (and user settings under `--global`) | Command Code project root (git root, or cwd outside a git repo), `$COMMANDCODE_PROJECT_DIR`, `$COMMANDCODE_CWD` |
|
|
534
591
|
|
|
535
592
|
`${CLAUDE_PLUGIN_ROOT}` is expanded **only** for a hook that came from a plugin.
|
|
536
593
|
In a settings file it names nothing, so the path is skipped rather than guessed
|
|
@@ -543,17 +600,18 @@ A value is only resolved when it is path-like and the answer is certain; shell
|
|
|
543
600
|
programs (`a && b`, `$(...)`, pipes), bare PATH binaries (`npx`, `uvx`), and
|
|
544
601
|
unresolved env vars are skipped. A false "broken" on a working `npx` server
|
|
545
602
|
would be worse than silence. `node -e "<code>"` is never treated as a path.
|
|
546
|
-
Only `$CLAUDE_PROJECT_DIR
|
|
547
|
-
|
|
548
|
-
shaped entry will start
|
|
603
|
+
Only `$CLAUDE_PROJECT_DIR`, `$COMMANDCODE_PROJECT_DIR`, and `$COMMANDCODE_CWD`
|
|
604
|
+
are expanded — other variables are left alone rather than guessed at. Schema
|
|
605
|
+
checks judge misconfiguration, not whether a correctly shaped entry will start
|
|
606
|
+
at runtime.
|
|
549
607
|
|
|
550
608
|
Spec-required checks are written against published pages, not against what
|
|
551
609
|
happens to appear in real projects. Two that were written the other way round
|
|
552
610
|
shipped as false positives — a nine-name hook-event list where the spec has 31,
|
|
553
611
|
and a `name` must equal the directory rule that Claude's spec explicitly
|
|
554
612
|
contradicts. Both are gone. Heuristics that remain (`skill.duplicate-description`,
|
|
555
|
-
the installer lock checks, and the size budgets other than `budget.claude-md`
|
|
556
|
-
are labeled in the registry and stay at `info`.
|
|
613
|
+
the installer lock checks, and the size budgets other than `budget.claude-md`
|
|
614
|
+
and `skill.description-budget`) are labeled in the registry and stay at `info`.
|
|
557
615
|
|
|
558
616
|
Assumptions are recorded in **[docs/spec/](docs/spec/)** with source URL, read
|
|
559
617
|
date, and provenance. When adding a spec-required check, add its spec line there
|
|
@@ -572,11 +630,28 @@ first.
|
|
|
572
630
|
- **Runtime split.** Source development and the composite Action use Bun; the
|
|
573
631
|
published `dist/cli.js` runs on Node 20.11+ or Bun. The source entrypoint uses
|
|
574
632
|
Bun's `import.meta.dir` / `import.meta.main` and is not the Node entrypoint.
|
|
575
|
-
- **
|
|
633
|
+
- **Command Code local MCP is unread.** `~/.commandcode/projects/{project}/mcp.json`
|
|
634
|
+
is keyed by a working-directory slug that the sessions page does not publish.
|
|
635
|
+
Until it does, that path is skipped rather than guessed. Bundled Command Code
|
|
636
|
+
skills and `--skill` launch flags are not project files and are not scanned.
|
|
637
|
+
`mods.paths` are inventoried; the TypeScript is never executed or imported.
|
|
638
|
+
`auth.json` and `mcp-tokens.json` are never opened. Command Code project
|
|
639
|
+
root is the git root (or cwd outside a git repo); a child `.cursor` does
|
|
640
|
+
not hide `<git-root>/.commandcode/`. Spec/runtime Command Code checks skip
|
|
641
|
+
shadowed lower-precedence definitions; secrets still inspect every readable
|
|
642
|
+
MCP file.
|
|
643
|
+
- **Three Claude hook locations are unread.** `~/.claude/settings.json`, managed policy
|
|
576
644
|
settings, and installed marketplace plugins under `~/.claude/plugins` all sit
|
|
577
645
|
outside the scanned project, and the docs say a plugin's install directory
|
|
578
646
|
changes on every update. A hook registered in one of those, pointing at a
|
|
579
647
|
missing script, is not reported.
|
|
648
|
+
- **Copilot CLI policy hooks are unread.** `/etc/github-copilot/policy.d` and the
|
|
649
|
+
Windows policy directory are machine-wide admin files. User
|
|
650
|
+
`~/.copilot/hooks` is scanned only under `--global`. Inline Copilot
|
|
651
|
+
`.github/copilot/settings.json` hooks are unread.
|
|
652
|
+
- **Gemini user settings are unread.** `~/.gemini/settings.json` is outside a
|
|
653
|
+
normal project scan. Windsurf's official MCP page is global-only and is not
|
|
654
|
+
scanned.
|
|
580
655
|
- **Bounded reads.** A `SKILL.md` is read to 64 KB and a policy file to 100 KB,
|
|
581
656
|
so `skill.broken-reference` and `policyLines` see only that much of a larger
|
|
582
657
|
file. This is reported — `scan.truncated`, at `info` — rather than left
|
|
@@ -590,6 +665,13 @@ Notes for every published version are in [CHANGELOG.md](CHANGELOG.md).
|
|
|
590
665
|
GitHub already has pages for [v0.1.0](https://github.com/SimaAlexandru99/agentscan/releases/tag/v0.1.0)
|
|
591
666
|
and [v0.4.0](https://github.com/SimaAlexandru99/agentscan/releases/tag/v0.4.0).
|
|
592
667
|
|
|
668
|
+
**1.1.0** (31 August 2026) adds a native Command Code provider and finishes the
|
|
669
|
+
correctness pass across registered checks: hook schema profiles, Agent Skills
|
|
670
|
+
optional fields, Claude listing budget, Codex chain knobs, and Copilot CLI
|
|
671
|
+
`version: 1` files. Still offline on `check`. Shared `.mcp.json` is `mcp-json`
|
|
672
|
+
(Claude and Command Code), not Claude-only — that MCP hotfix is **1.0.1** in
|
|
673
|
+
the changelog and ships inside this package version.
|
|
674
|
+
|
|
593
675
|
**1.0.0** (30 August 2026) is the first stable release: 59 checks, 345 tests,
|
|
594
676
|
still offline on `check`. It adds portable Agent Skills (including Cursor and
|
|
595
677
|
Codex skill trees), MCP profiles for VS Code / Cursor / Codex / Antigravity /
|