codex-plugin-doctor 1.69.1 → 1.71.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 CHANGED
@@ -1,661 +1,675 @@
1
- # Codex Plugin Doctor
2
-
3
- [![CI](https://github.com/Esquetta/CodexPluginDoctor/actions/workflows/ci.yml/badge.svg)](https://github.com/Esquetta/CodexPluginDoctor/actions/workflows/ci.yml)
4
- [![npm version](https://img.shields.io/npm/v/codex-plugin-doctor.svg)](https://www.npmjs.com/package/codex-plugin-doctor)
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE)
6
- [![GitHub release](https://img.shields.io/github/v/release/Esquetta/CodexPluginDoctor)](https://github.com/Esquetta/CodexPluginDoctor/releases)
7
-
8
- Codex Plugin Doctor is a local CLI validator for Codex plugin packages, skills, and MCP server bundles.
9
-
10
- It catches packaging, metadata, security, and runtime protocol problems before a plugin reaches users, teammates, or release workflows.
11
-
12
- ## Status
13
-
14
- Codex Plugin Doctor is a public stable CLI for local and CI validation.
15
-
16
- - Primary surface: GitHub repository and npm package
17
- - Distribution today: `npm install -g`, local source install, `npm link`, `npm pack`, GitHub Releases
18
- - Public npm package: `codex-plugin-doctor`
19
- - License: [MIT](./LICENSE)
20
-
21
- ## 1.0 Stability
22
-
23
- The 1.0 line is the stable compatibility baseline for plugin authors and CI consumers.
24
-
25
- - Public JSON schema surfaces and existing rule IDs/default severities are treated as stable through 1.0.
26
- - Runtime probing remains opt-in because it executes package-local MCP servers.
27
- - The project remains Codex-first; broader MCP Doctor positioning stays a post-1.0 expansion path.
28
- - Post-1.0 feature work should stay additive unless a documented major-version decision is made.
29
-
30
- See the [documentation index](./docs/README.md) for architecture, usage, security, and contributor guides.
31
-
32
- ## Why This Exists
33
-
34
- Codex plugin packages can fail in several places:
35
-
36
- - the package manifest is missing or points outside the package root
37
- - skills exist but do not expose valid `SKILL.md` metadata
38
- - `.mcp.json` is malformed or references unsafe secrets
39
- - an MCP server starts but does not complete the protocol handshake
40
- - tools, resources, or prompts list successfully but fail deeper runtime checks
41
- - verbose metadata creates noisy matching and unnecessary context cost
42
-
43
- This tool gives plugin authors a repeatable preflight check before distribution.
44
-
45
- ## What It Checks
46
-
47
- Static validation:
48
-
49
- - required `.codex-plugin/plugin.json`
50
- - manifest fields: `name`, `version`, `description`
51
- - skill directory wiring
52
- - `SKILL.md` presence and frontmatter fields
53
- - YAML single-line and block-scalar skill descriptions
54
- - `.mcp.json` structure
55
- - path traversal risks
56
- - hard-coded secret-like env values
57
- - description quality heuristics tuned against real plugin packages
58
-
59
- Security scorecard with `security`:
60
-
61
- - shell wrapper command warnings for MCP servers
62
- - encoded shell command failures
63
- - remote content piped into shell failures
64
- - MCP server `cwd` paths that escape the package root
65
- - plain HTTP remote transport warnings
66
-
67
- Runtime MCP validation with `--runtime`:
68
-
69
- - `initialize`
70
- - `notifications/initialized`
71
- - `tools/list`
72
- - `tools/call`
73
- - `resources/list`
74
- - `resources/read`
75
- - `resources/templates/list`
76
- - `prompts/list`
77
- - `prompts/get`
78
- - paginated list responses
79
- - runtime capability scorecard
80
- - redacted verbose transcript with `--verbose-runtime`
81
- - optional runtime approval gating with a precomputed `doctor runtime-plan` digest
82
- - optional Docker isolation for local Node.js stdio servers with `--sandbox docker`
83
-
84
- ### MCP Protocol Discovery
85
-
86
- Inspect an HTTP MCP endpoint's advertised protocol versions using a bounded MCP
87
- 2026-07-28 `server/discover` request:
88
-
89
- ```bash
90
- codex-plugin-doctor doctor discover https://mcp.example.com/mcp --allow-network
91
- codex-plugin-doctor doctor discover https://mcp.example.com/mcp --allow-network --json
92
- ```
93
-
94
- This is an opt-in discovery-only check. A successful result validates the discovery
95
- response, not full protocol conformance, tool behavior, or compatibility with a
96
- particular client. Existing `check --runtime` remains on its 2025-11-25 baseline.
97
- See [MCP Discovery](docs/guides/mcp-discovery.md) for consent, scope, and exit codes.
98
-
99
- ### Offline MCP Tool Definitions
100
-
101
- Inspect a saved MCP 2026-07-28 `tools/list` response without contacting a server:
102
-
103
- ```bash
104
- codex-plugin-doctor doctor tools-file ./tools-list.json --json
105
- ```
106
-
107
- This checks the supplied tool definitions and root-schema shapes within fixed file,
108
- tool, and finding limits. It does not establish server inventory completeness or
109
- execute tools. See [Offline MCP Tool Definitions](docs/guides/offline-tool-definitions.md)
110
- for the accepted input format, coverage, and exit codes.
111
-
112
- ### Offline MCP Tool Diff
113
-
114
- Compare two saved tool-list responses before updating a server or client:
115
-
116
- ```bash
117
- codex-plugin-doctor doctor tools-diff --before ./tools-old.json --after ./tools-new.json --json
118
- ```
119
-
120
- This reports added, removed, and structurally changed definitions using numeric
121
- locations, and labels each change `breaking`, `compatible`, or `unclassified`
122
- with fixed reason codes. Add `--fail-on breaking` to fail CI only on breaking or
123
- unclassified changes, and `--markdown` for pull request tables. Incomplete inputs, invalid definitions, or duplicate names
124
- prevent a comparison. Impact labels follow nested object properties, array
125
- items, and common length and range bounds, but remain heuristics, not proof of
126
- compatibility.
127
- See [Offline MCP Tool Diff](docs/guides/offline-tool-diff.md) for matching rules,
128
- privacy, limits, and exit codes.
129
-
130
- ### HTTP MCP Tool Catalog
131
-
132
- Inspect a modern HTTP MCP server's tool definitions without invoking them:
133
-
134
- ```bash
135
- codex-plugin-doctor doctor tools https://mcp.example.com/mcp --allow-network --json
136
- ```
137
-
138
- This opt-in command performs discovery and bounded `tools/list` pagination. It
139
- reports tool-definition and root-schema shape findings, explicit completion state,
140
- and partial inspection limits. It does not claim full schema validation, tool
141
- execution, or client compatibility. Existing `doctor discover` behavior is unchanged.
142
- Add `--save-response <path>` to record a completely enumerated catalog as a
143
- `tools/list` response for `tools-file` and `tools-diff`; nothing is written when
144
- enumeration is incomplete. For protected servers, `--bearer-token-env <NAME>`
145
- sends a bearer token from an environment variable only over HTTPS or to an
146
- approved loopback endpoint; it is never printed or saved. The GitHub Action can compare saved responses with
147
- `tools-diff-before`, `tools-diff-after`, and `tools-diff-fail-on`, capture the
148
- live list with `tools-capture-url` (and `tools-capture-token-env`), and skip the
149
- plugin package check with `check: "false"` in repositories that only ship an MCP
150
- server.
151
- See [HTTP MCP Tool Catalog](docs/guides/mcp-tool-catalog.md).
152
-
153
- ### Remote MCP Readiness
154
-
155
- Remote MCP runtime probing is disabled until you explicitly pass `--runtime --allow-network`. Loopback endpoints also require `--allow-local-network`:
156
-
157
- ```bash
158
- codex-plugin-doctor check ./remote-mcp --runtime --allow-network
159
- codex-plugin-doctor check ./remote-mcp --runtime --allow-network --allow-local-network
160
- ```
161
-
162
- The probe makes only bounded protocol and OAuth metadata-discovery requests, redacts report output, and applies SSRF controls. It does not authenticate or follow redirects.
163
-
164
- Remote transport reliability adds one bounded SSE GET after initialization. HTTP `200` must be `text/event-stream`; HTTP `405` is compliant when the endpoint does not offer server-to-client SSE. At most one SSE resume and one session restart are attempted, and no remote response content is retained. This is a bounded readiness check, not a live interoperability, delivery-guarantee, or load-test claim.
165
-
166
- `--allow-session-lifecycle` is disabled by default and is state-changing: only after a valid `MCP-Session-Id` it permits one bounded session `DELETE`. `--require-remote-reliability` is a strict result gate: it fails unless every attempted remote reliability scorecard passes. Local-only runs are unaffected. It grants no network consent, so `--runtime --allow-network` (and loopback consent when applicable) remain required. See [Remote MCP Readiness](./docs/architecture/remote-mcp-readiness.md) and [Remote MCP Transport Reliability](./docs/architecture/remote-mcp-transport-reliability.md).
167
-
168
- ### MCP Registry Readiness
169
-
170
- Validate official MCP Registry publication metadata without publishing or installing anything:
171
-
172
- ```bash
173
- codex-plugin-doctor registry check path/to/server.json
174
- codex-plugin-doctor registry check path/to/server.json --json --require-registry-readiness
175
- codex-plugin-doctor registry inspect io.github.example/weather --allow-network
176
- ```
177
-
178
- Local checks validate metadata, ownership consistency, package integrity, transports, and Codex installability. Exact Registry lookup is read-only, requires explicit network consent, and contacts only the fixed official Registry endpoint. It never follows advertised package, icon, repository, or remote MCP URLs. See [MCP Registry Readiness](./docs/architecture/mcp-registry-readiness.md).
179
-
180
- ### MCP Registry Publication Preflight
181
-
182
- Check a publication candidate locally without making a network request:
183
-
184
- ```bash
185
- codex-plugin-doctor registry preflight path/to/server.json --json
186
- ```
187
-
188
- Opt in to bounded public npm and MCP Registry metadata checks:
189
-
190
- ```bash
191
- codex-plugin-doctor registry preflight path/to/server.json --allow-network --json
192
- ```
193
-
194
- Require a publish-ready result in CI:
195
-
196
- ```bash
197
- codex-plugin-doctor registry preflight path/to/server.json --allow-network --require-publish-ready --json
198
- ```
199
-
200
- Preflight checks the exact npm package version, then the exact Registry version
201
- and latest Registry record on fixed public hosts. An existing exact Registry
202
- version is an immutable collision and must be replaced by a version bump. The
203
- command is advisory: it never authenticates, publishes, or changes npm or
204
- Registry records. See [MCP Registry Publication Preflight](./docs/architecture/mcp-registry-publication-preflight.md).
205
-
206
- ### Public Directory Submission Preflight
207
-
208
- Check a plugin package for deterministic public-directory submission issues without contacting a portal:
209
-
210
- ```bash
211
- codex-plugin-doctor doctor submission <path>
212
- codex-plugin-doctor doctor submission <path> --json
213
- codex-plugin-doctor doctor submission <path> --markdown
214
- codex-plugin-doctor doctor submission <path> --require-ready
215
- codex-plugin-doctor doctor submission archive <zip>
216
- codex-plugin-doctor doctor submission archive <zip> --json --output submission-archive.json
217
- codex-plugin-doctor doctor submission archive <zip> --markdown --output submission-archive.md
218
- codex-plugin-doctor doctor submission archive <zip> --require-ready
219
- ```
220
-
221
- The preflight is offline and non-executing: it does not submit a package, make network requests, start MCP servers, verify domains, or handle OAuth credentials. Its automatic `status` is `pass` or `fail`; a passing automatic result remains `manual_review_required` until portal-only review is complete. It never claims directory acceptance. See [Public Directory Submission Preflight](./docs/architecture/public-directory-submission-preflight.md).
222
-
223
- The archive variant accepts an existing skills-only ZIP and does not extract archive entries to disk, execute package code, or repair the archive. It reports malformed ZIP structures and deterministic package blockers; unsupported portal rules remain manual or `coverage: unavailable` rather than an automatic pass.
224
-
225
- Output formats:
226
-
227
- - human text output
228
- - JSON reports
229
- - Markdown reports
230
- - Shields-compatible badge JSON and static badge Markdown
231
- - validation history JSONL and trend summaries
232
- - deterministic local attestation artifacts
233
- - output contract and rule catalog freeze metadata
234
- - bundled validation corpus reports
235
- - `--output` file writing
236
- - CI summary and artifact generation
237
-
238
- ## Quick Start
239
-
240
- Global install from npm:
241
-
242
- ```bash
243
- npm install -g codex-plugin-doctor
244
- codex-plugin-doctor --version
245
- codex-plugin-doctor self-test
246
- codex-plugin-doctor check path/to/plugin-package
247
- ```
248
-
249
- Run `codex-plugin-doctor check .` from the root of a Codex plugin package that contains `.codex-plugin/plugin.json`. The Codex Plugin Doctor source repository is not itself a plugin package.
250
-
251
- If you already have Codex installed locally and do not know plugin paths, discover the installed plugin cache:
252
-
253
- ```bash
254
- codex-plugin-doctor list --installed
255
- codex-plugin-doctor check --installed
256
- codex-plugin-doctor check --installed --all-summary
257
- codex-plugin-doctor check --installed --compat --all-summary
258
- codex-plugin-doctor audit --installed --security --compat
259
- codex-plugin-doctor audit --installed --security --compat --policy security
260
- codex-plugin-doctor mcp path/to/mcp-package
261
- codex-plugin-doctor check --installed github
262
- codex-plugin-doctor explain plugin.manifest.missing
263
- ```
264
-
265
- Run from source:
266
-
267
- ```bash
268
- npm install
269
- npm run build
270
- node dist/cli.js check examples/codex-doctor-runtime --runtime
271
- ```
272
-
273
- For local global usage:
274
-
275
- ```bash
276
- npm link
277
- codex-plugin-doctor check examples/codex-doctor-runtime --runtime
278
- ```
279
-
280
- Generate validation artifacts locally:
281
-
282
- ```bash
283
- npm run generate-validation-artifacts -- --target examples/codex-doctor-runtime --runtime-target examples/codex-doctor-runtime --out-dir validation-artifacts-local
284
- ```
285
-
286
- ## Example Output
287
-
288
- Passing runtime package:
289
-
290
- ```text
291
- Codex Plugin Doctor
292
- ===================
293
- Status: PASS
294
- Target: <repo>\examples\codex-doctor-runtime
295
- Summary: 0 fail, 0 warn, 0 total
296
-
297
- Runtime Scorecard
298
- ----------------
299
- initialize: pass
300
- tools/list: pass
301
- tools/call: pass
302
- resources/list: pass
303
- resources/read: pass
304
- resources/templates/list: pass
305
- prompts/list: pass
306
- prompts/get: pass
307
-
308
- No findings.
309
- ```
310
-
311
- Risky package:
312
-
313
- ```text
314
- Codex Plugin Doctor
315
- ===================
316
- Status: FAIL
317
- Target: <repo>\examples\codex-doctor-risky
318
- Summary: 1 fail, 0 warn, 1 total
319
-
320
- Failures
321
- --------
322
- x plugin.security.hard_coded_secret
323
- Message: The MCP server `dangerServer` contains a hard-coded secret-like env value for `OPENAI_API_KEY`.
324
- Impact: Hard-coded credentials inside plugin bundles increase leakage risk and make secure rotation difficult.
325
- Suggested fix: Replace the literal value for `OPENAI_API_KEY` with an environment reference or injected secret outside the package.
326
- ```
327
-
328
- ## Useful Commands
329
-
330
- Run these from a Codex plugin package root:
331
-
332
- ```bash
333
- codex-plugin-doctor --version
334
- codex-plugin-doctor self-test
335
- codex-plugin-doctor doctor
336
- codex-plugin-doctor doctor contract
337
- codex-plugin-doctor doctor contract --json --output output-contract.json
338
- codex-plugin-doctor doctor corpus
339
- codex-plugin-doctor doctor corpus --json --output validation-corpus.json
340
- codex-plugin-doctor doctor corpus --manifest ../private-corpus/corpus.json --json
341
- codex-plugin-doctor doctor corpus metrics --manifest ../private-corpus/metrics.json --markdown
342
- codex-plugin-doctor doctor corpus metrics --manifest ../private-corpus/metrics.json --json --min-precision 0.90 --min-recall 0.85 --max-false-positive-rate 0.10
343
- codex-plugin-doctor doctor npm <published-plugin-package>
344
- codex-plugin-doctor doctor npm <published-plugin-package> --json --output npm-preinstall.json
345
- codex-plugin-doctor doctor attest .
346
- codex-plugin-doctor doctor attest . --json --output attestation.json
347
- codex-plugin-doctor doctor attest . --json --sign-key-env CODEX_PLUGIN_DOCTOR_SIGNING_KEY --output attestation.json
348
- codex-plugin-doctor doctor attest verify attestation.json --target . --sign-key-env CODEX_PLUGIN_DOCTOR_SIGNING_KEY
349
- codex-plugin-doctor doctor attest verify attestation.json --target . --json --sign-key-env CODEX_PLUGIN_DOCTOR_SIGNING_KEY
350
- codex-plugin-doctor doctor inspector .
351
- codex-plugin-doctor doctor inspector . --server context7 --json --output inspector-command.json
352
- codex-plugin-doctor doctor diff --before ./old-plugin --after ./new-plugin
353
- codex-plugin-doctor doctor diff --before ./old-plugin --after ./new-plugin --json --output risk-diff.json
354
- codex-plugin-doctor doctor recommend .
355
- codex-plugin-doctor doctor recommend . --json --output recommendations.json
356
- codex-plugin-doctor doctor trust .
357
- codex-plugin-doctor doctor trust . --json --output trust-score.json
358
- codex-plugin-doctor doctor perf .
359
- codex-plugin-doctor doctor perf . --json --output perf.json
360
- codex-plugin-doctor doctor perf . --max-total-ms 2500 --max-stage-ms validation=500
361
- codex-plugin-doctor doctor runtime-plan .
362
- codex-plugin-doctor doctor runtime-plan . --json --output runtime-plan.json
363
- codex-plugin-doctor doctor runtime-plan . --markdown --output runtime-plan.md
364
- codex-plugin-doctor doctor runtime-plan . --sandbox docker --json
365
- codex-plugin-doctor doctor runtime-policy .
366
- codex-plugin-doctor doctor runtime-policy . --json --output runtime-policy.json
367
- codex-plugin-doctor doctor runtime-policy . --sandbox docker --json
368
- codex-plugin-doctor doctor review-bundle . --output review-bundle --sign-key-env CODEX_PLUGIN_DOCTOR_SIGNING_KEY
369
- codex-plugin-doctor doctor review-bundle verify review-bundle --target . --sign-key-env CODEX_PLUGIN_DOCTOR_SIGNING_KEY
370
- codex-plugin-doctor doctor review-bundle diff --before old-review-bundle --after review-bundle
371
- codex-plugin-doctor doctor mcp .
372
- codex-plugin-doctor doctor mcp . --json --output mcp-healthcheck.json
373
- codex-plugin-doctor doctor export --bundle .
374
- codex-plugin-doctor doctor export --bundle . --output doctor-bundle.json
375
- codex-plugin-doctor doctor snapshot
376
- codex-plugin-doctor doctor snapshot --json
377
- codex-plugin-doctor doctor snapshot --output doctor-snapshot.json
378
- codex-plugin-doctor doctor clients
379
- codex-plugin-doctor doctor --update-check
380
- codex-plugin-doctor audit --installed
381
- codex-plugin-doctor audit --installed --security --compat
382
- codex-plugin-doctor audit --installed --security --compat --json --output local-audit.json
383
- codex-plugin-doctor audit --installed --security --compat --cache
384
- codex-plugin-doctor audit --installed --changed --cache
385
- codex-plugin-doctor audit deps .
386
- codex-plugin-doctor audit deps . --json --output dependency-audit.json
387
- codex-plugin-doctor audit deps . --recommend
388
- codex-plugin-doctor audit deps . --recommend --json --output dependency-remediation.json
389
- codex-plugin-doctor watch .
390
- codex-plugin-doctor watch . --json --output watch-latest.json --debounce-ms 500
391
- codex-plugin-doctor init-git-hooks .
392
- codex-plugin-doctor init-git-hooks . --json
393
- codex-plugin-doctor mcp .
394
- codex-plugin-doctor mcp . --json
395
- codex-plugin-doctor mcp . --json --output mcp-doctor.json
396
- codex-plugin-doctor init my-plugin
397
- codex-plugin-doctor init my-mcp --template mcp-stdio
398
- codex-plugin-doctor init remote-mcp --template mcp-http
399
- codex-plugin-doctor init runtime-demo --template full-runtime
400
- codex-plugin-doctor security .
401
- codex-plugin-doctor security . --scorecard
402
- codex-plugin-doctor security . --json
403
- codex-plugin-doctor security . --policy security
404
- codex-plugin-doctor compat .
405
- codex-plugin-doctor compat . --all --scorecard
406
- codex-plugin-doctor compat . --client codex
407
- codex-plugin-doctor compat . --client generic-mcp
408
- codex-plugin-doctor compat . --client claude-desktop
409
- codex-plugin-doctor compat . --client claude-desktop --install-preview
410
- codex-plugin-doctor compat . --client claude-desktop --apply --backup
411
- codex-plugin-doctor compat . --client cursor
412
- codex-plugin-doctor compat . --client cursor --install-preview
413
- codex-plugin-doctor compat . --client cursor --apply --backup
414
- codex-plugin-doctor compat . --client cline
415
- codex-plugin-doctor compat . --client cline --install-preview
416
- codex-plugin-doctor compat . --scorecard
417
- codex-plugin-doctor compat . --json
418
- codex-plugin-doctor compat . --json --output compatibility.json
419
- codex-plugin-doctor check .
420
- codex-plugin-doctor check . --profile ci
421
- codex-plugin-doctor check . --profile strict
422
- codex-plugin-doctor check . --profile publish
423
- codex-plugin-doctor check . --policy codex-publish
424
- codex-plugin-doctor check . --policy mcp-strict
425
- codex-plugin-doctor check . --policy security
426
- codex-plugin-doctor check . --json
427
- codex-plugin-doctor check . --explain
428
- codex-plugin-doctor check . --json --output report.json
429
- codex-plugin-doctor check . --markdown --output report.md
430
- codex-plugin-doctor check . --badge-json --output doctor-badge.json
431
- codex-plugin-doctor check . --badge-markdown
432
- codex-plugin-doctor check . --sarif --output results.sarif
433
- codex-plugin-doctor check . --ascii
434
- codex-plugin-doctor check . --no-animations
435
- codex-plugin-doctor check . --runtime
436
- codex-plugin-doctor check . --runtime --require-runtime-approval --runtime-approval-digest sha256:<approved-plan-digest>
437
- codex-plugin-doctor check . --runtime --sandbox docker
438
- codex-plugin-doctor check . --runtime --sandbox docker --require-runtime-approval --runtime-approval-digest sha256:<approved-docker-plan-digest>
439
- codex-plugin-doctor release check .
440
- codex-plugin-doctor release check . --json
441
- codex-plugin-doctor release check . --runtime
442
- codex-plugin-doctor release check . --runtime --require-runtime-approval --runtime-approval-digest sha256:<approved-plan-digest>
443
- codex-plugin-doctor release check . --runtime --sandbox docker --require-runtime-approval --runtime-approval-digest sha256:<approved-docker-plan-digest>
444
- codex-plugin-doctor check . --config .codex-doctor.json
445
- codex-plugin-doctor baseline create . --output .codex-doctor-baseline.json
446
- codex-plugin-doctor check . --baseline .codex-doctor-baseline.json
447
- codex-plugin-doctor check . --history validation-history.jsonl
448
- codex-plugin-doctor history validation-history.jsonl
449
- codex-plugin-doctor history validation-history.jsonl --json
450
- codex-plugin-doctor history validation-history.jsonl --fail-on-regression
451
- codex-plugin-doctor fix . --dry-run
452
- codex-plugin-doctor fix . --interactive --backup
453
- codex-plugin-doctor fix . --apply --backup
454
- codex-plugin-doctor check . --json --runtime --verbose-runtime
455
- ```
456
-
457
- Docker runtime mode supports local Node.js stdio MCP servers. It uses a digest-pinned image, no network, read-only container and package filesystems, an unprivileged user, dropped capabilities, bounded resources, and a limited writable `/tmp`. It fails closed without native fallback and rejects package roots containing commas. The Docker daemon, base image, and host kernel remain trusted boundaries. Generate approval digests with the same `--sandbox docker` backend used for execution. See [Runtime Approval And Sandboxing](./docs/security/runtime-approval-and-sandboxing.md).
458
-
459
- External corpus evaluation is static and offline. `doctor corpus --manifest <corpus.json>` validates anonymized local snapshots using stable content digests and exact finding fingerprints without downloading dependencies or starting target servers. Reports omit manifest and package paths and fail on digest drift, missing expected findings, present disputed findings, or unreviewed findings. See [Real-World Validation](./docs/guides/real-world-validation.md).
460
-
461
- `doctor corpus metrics --manifest <corpus.json>` measures reviewed true positives, false positives, and false negatives as precision, recall, and emitted-finding false-positive share. Optional thresholds make the measurement release-gating; incomplete reviews and digest drift return exit `2` instead of producing a favorable score. The dedicated metrics manifest stays offline, requires contained snapshot paths, and may record immutable HTTPS Git provenance without fetching it.
462
-
463
- `doctor corpus metrics diff --before <metrics.json> --after <metrics.json>` compares two complete metrics reports from the same corpus identity. Add `--fail-on-regression` to fail CI when precision or recall decreases, or when the reviewed emitted-finding false-positive share increases. Reports with different `corpusDigest` values are rejected as non-comparable, and diff output never includes the input report paths.
464
-
465
- `self-test` runs the bundled runtime-complete sample through static validation, runtime MCP probes, and the compatibility scorecard. It is the fastest post-install check after `npm install -g codex-plugin-doctor`.
466
-
467
- `doctor` checks the local environment, including package version, platform, Node version, npm global prefix, Codex home, and Codex plugin cache visibility. The text output also includes recommended next commands for self-test, installed plugin discovery, runtime checks, compatibility scoring, and CI setup. `doctor contract` publishes the machine-readable output contract, including public JSON schema surfaces, stable-through-1.0 compatibility metadata, and a frozen rule catalog digest. Add `--json` for automation or `--output output-contract.json` to write the contract to disk. `doctor corpus` runs the bundled validation corpus against healthy runtime, risky security, starter skill, and generic MCP packages, then reports whether each case matched its expected outcome. Add `--json` for automation or `--output validation-corpus.json` to write the corpus report to disk. `doctor npm <package>` runs a preinstall scan by packing the npm package with scripts disabled, extracting the publish tarball, and running validation, security, trust, and recommendation checks against the shipped contents. The JSON report includes tarball metadata such as filename, path, integrity, shasum, sizes, file count, and extracted package root so automation can prove which archive was scanned. Use a published Codex plugin package as the target; scanning `codex-plugin-doctor` itself intentionally reports a missing plugin manifest because this CLI package is not a plugin package. Add `--json` for automation or `--output npm-preinstall.json` to write the report to disk. `doctor attest <path>` creates a local attestation with stable package/report digests, validation/security/compatibility/trust summary, and verification metadata. Add `--sign-key-env NAME` to attach a local HMAC-SHA256 signature without printing the secret, or `--json --output attestation.json` to write the artifact to disk. `doctor attest verify <attestation.json> --target <path> --sign-key-env NAME` recomputes the package fingerprint, report digest, and HMAC signature offline; verification intentionally treats `generatedAt`, `targetPath`, `verification`, and `signature.keyHint` as unsigned display metadata. `doctor runtime-plan <path>` creates a non-executing runtime plan that lists MCP server commands, safe probe methods, risk reasons, and a stable approval digest before any local server is started. Add `--markdown --output runtime-plan.md` to preserve a review-ready approval artifact with the execution boundary, checklist, servers, probes, and risk reasons. `doctor runtime-policy <path>` evaluates the same runtime plan and security signals, then recommends `allow`, `review`, `sandbox_recommended`, or `deny` before local MCP execution starts. `doctor review-bundle <path> --output <dir> --sign-key-env NAME` writes a signed review directory with runtime plan, runtime policy, attestation, release evidence, manifest, Markdown summary files, and SHA-256 file integrity digests. `doctor review-bundle verify <bundle-dir> --target <path> --sign-key-env NAME` verifies the bundle manifest, expected files, manifest integrity digests, runtime artifacts, signed attestation, and signed release evidence offline before a reviewer trusts the handoff. `doctor review-bundle diff --before <dir> --after <dir>` compares two review bundles and flags risk-increasing changes in status, runtime policy, release readiness, signatures, release evidence, and runtime plan digest. `check --runtime --require-runtime-approval --runtime-approval-digest <digest>` refuses to run runtime probes unless the current plan digest matches the approved digest. `doctor release-evidence <path> --sign-key-env NAME` creates one redacted release bundle with signed attestation, offline verification, corpus, performance, security, trust, package metadata, git release gates, and runtime approval status. Strict release evidence requires a clean tagged worktree; use `--allow-dirty` or `--allow-untagged` only for local rehearsal. `doctor release-evidence verify <evidence.json> --target <path> --sign-key-env NAME` verifies a shared release evidence artifact offline against an explicit package path; the artifact target path is treated as display metadata, not trusted input. `doctor release-evidence asset <path> --tag <tag> --output <evidence.json> --sign-key-env NAME` writes a signed release evidence file and prints the `gh release upload` command; add `--upload` to run the upload through GitHub CLI with `--clobber`. `doctor inspector <path>` builds a safe MCP Inspector launch command from a packaged `.mcp.json` file without starting the Inspector proxy automatically. Use `--server <name>` when the package contains multiple MCP server entries. `doctor diff --before <path> --after <path>` compares two package roots and reports new findings, resolved findings, trust score delta, and whether risk increased. `doctor recommend <path>` turns validation, security, and compatibility signals into a prioritized action plan with blocker, high, medium, and info actions. Add `--json` for automation or `--output recommendations.json` to write the report to disk. `doctor trust <path>` creates a local trust score from package lifecycle scripts, dependency specs, and MCP security findings. Use it before release when you want supply-chain risks summarized as one score. `doctor perf <path>` profiles the shared package analysis pipeline and reports per-stage durations for validation, config, security, compatibility, trust, recommendations, and total runtime. Add `--max-total-ms <ms>` or repeatable `--max-stage-ms stage=ms` to fail CI when a budget is exceeded. `doctor mcp <path>` exposes the generic MCP static health report under the doctor command family without starting local MCP servers. `doctor export --bundle <path>` creates a redacted operator handoff bundle that includes validation JSON, security scorecard data, compatibility matrix, recommendations, and trust score in one file. `doctor snapshot` creates a redacted diagnostics bundle with environment health, client config readiness, installed plugin metadata, and next commands. Add `--json` for machine-readable output or `--output doctor-snapshot.json` to write the bundle to disk. `doctor clients` reports local Codex, Claude Desktop, Cursor, Cline, and Windsurf config readiness. `doctor --update-check` compares the installed CLI version with the latest npm version and prints the upgrade command when a newer release is available.
468
-
469
- `audit --installed` runs a local ecosystem audit against every discovered Codex plugin in the installed plugin cache. Add `--security` to include security scorecards, `--compat` to include the all-client compatibility matrix, and `--json --output local-audit.json` when you want a shareable machine-readable report. Add `--cache` to reuse unchanged plugin results between runs; add `--changed` to only report plugins whose fingerprint changed since the last cached audit. Use `--cache-file path/to/audit-cache.json` when CI or scripted runs need an explicit cache location.
470
-
471
- `audit deps <path>` runs `npm audit --json` for the target package and normalizes dependency vulnerability results into a stable `schemaVersion: "1.0.0"` report. Use `--json --output dependency-audit.json` when CI needs machine-readable status, vulnerability counts, and the raw npm audit payload. Add `--recommend` to include prioritized remediation actions for direct upgrades, direct no-fix packages, transitive parent updates, and manual transitive review.
472
-
473
- `watch <path>` continuously validates a plugin package after file changes. Use `--debounce-ms <ms>` to tune noisy repositories, `--runtime` when runtime probes are required, and `--json --output watch-latest.json` when another process should consume the latest validation snapshot.
474
-
475
- `init-git-hooks [path]` installs generated pre-commit and pre-push hooks that run Codex Plugin Doctor validation before local commits and pushes. Add `--force` to overwrite existing hooks and `--json` when setup automation needs the written hook paths.
476
-
477
- `--policy codex-publish|mcp-strict|security` applies opinionated gates without requiring a local `.codex-doctor.json`. `codex-publish` fails warnings and enables runtime probes for release checks, `mcp-strict` does the same for MCP-heavy packages, and `security` fails warning-level security findings so advisory risks can block a local audit or CI gate.
478
-
479
- `mcp <path>` diagnoses generic MCP packages that may not have a Codex plugin manifest. It looks for `.mcp.json` or a manifest `mcpServers` reference, validates the top-level `mcpServers` object and server transports, adds MCP command-surface security findings, and includes the all-client compatibility matrix in the same report.
480
-
481
- `init [path] --template ...` creates targeted starter packages. `skill-only` is the default minimal skill package, `mcp-stdio` adds a local stdio MCP config and mock server, `mcp-http` scaffolds a streamable HTTP MCP config, and `full-runtime` generates a stdio sample that passes the runtime protocol probes.
482
-
483
- `security <path>` renders a focused package security scorecard. It reuses the existing package security findings, then adds deeper MCP command-surface checks for shell wrappers, encoded shell payloads, remote pipe-to-shell startup patterns, `cwd` values outside the plugin root, and plain HTTP URLs. Findings include structured, instance-specific evidence such as manifest fields, skill paths, server names, protocol methods, dependency sections, env keys, and bounded payload lengths. Deterministic SHA-256 fingerprints derive from the rule ID and canonical evidence, with package paths normalized for cross-machine stability. Secrets, prompt bodies, resource contents, tool payloads, stderr, and encoded commands are not copied into evidence. Use `--json` for automation or `--scorecard` for a compact status view.
484
-
485
- `compat --client claude-desktop` checks whether the MCP package can be added to the local Claude Desktop setup. On Windows it looks for `%APPDATA%\Claude\claude_desktop_config.json`; on macOS it looks for `~/Library/Application Support/Claude/claude_desktop_config.json`. A valid existing config returns `PASS`, a missing Claude Desktop install returns `WARN`, and a malformed local config returns `FAIL` so you do not add new servers into a broken config file. If the package server name already exists in Claude Desktop, the command returns `WARN` with the duplicate server name. Add `--install-preview` to print the JSON snippet that should be merged into `claude_desktop_config.json`; it does not modify files. Use `--apply --backup` only when you want the CLI to create a timestamped backup and merge the server config. Apply mode refuses to overwrite duplicate server names.
486
-
487
- `compat --client cursor` checks whether the MCP package can be added to Cursor. It prefers a project-level `.cursor/mcp.json` when one already exists in the target package, then falls back to the global `~/.cursor/mcp.json` path. A valid existing config returns `PASS`, a missing Cursor config returns `WARN`, malformed JSON returns `FAIL`, and duplicate MCP server names return `WARN`. Add `--install-preview` to print the JSON snippet that should be merged into Cursor's `mcp.json`; it does not modify files. Use `--apply --backup` only when you want the CLI to create a timestamped backup and merge the server config. Apply mode refuses to overwrite duplicate server names.
488
-
489
- `compat --client cline` checks whether the MCP package can be added to Cline. It uses `CLINE_DIR/data/settings/cline_mcp_settings.json` when `CLINE_DIR` is set, otherwise `~/.cline/data/settings/cline_mcp_settings.json`. Add `--install-preview` to print the JSON snippet that should be merged into `cline_mcp_settings.json`.
490
-
491
- `compat --all` makes the all-client matrix explicit when you want Codex, Generic MCP, Claude Desktop, Cursor, Cline, and Windsurf in one run. `compat --scorecard` turns the compatibility matrix into a compact score summary. `PASS` maps to `100`, `WARN` maps to `70`, and `FAIL` or `SKIPPED` maps to `0`.
492
-
493
- `check --installed --compat --all-summary` validates every discovered Codex plugin from the local plugin cache and appends a compact compatibility summary for Codex, Generic MCP, Claude Desktop, Cursor, Cline, and Windsurf. This is the fastest repo-free audit when a user does not know individual plugin paths.
494
-
495
- `check --profile ci|strict|publish` applies named validation policies. `ci` keeps default behavior, `strict` fails on warnings, and `publish` fails on warnings while enabling runtime probing by default.
496
-
497
- `check --explain` adds a deduplicated `Next Actions` summary plus inline rule catalog context to text reports, including the problem summary, rule category, why a finding matters, a more detailed fix path, a compact example, and the matching `codex-plugin-doctor explain <finding-id>` follow-up command.
498
-
499
- `check --badge-json` emits Shields endpoint-compatible JSON such as `{"schemaVersion":1,"label":"doctor","message":"PASS","color":"brightgreen"}`. `check --badge-markdown` emits a static shields.io Markdown badge for README or release notes. Badge output is intentionally limited to single package checks, not `check --installed`.
500
-
501
- `check --history <path>` appends a compact JSONL validation snapshot after a single package check. `history <path>` reads the JSONL file and compares the latest run to the previous run, including status, finding-count deltas, and whether the latest run regressed. Add `history --json` for automation output or `history --fail-on-regression` when CI should fail after a worse latest run.
502
-
503
- `baseline create <path> --output <path>` records the current fingerprinted findings for gradual CI adoption. A later `check <path> --baseline <path>` keeps matched findings visible in baseline metadata but gates only new active findings; reports summarize new, matched, and resolved counts. Commit the baseline for review and regenerate it deliberately after accepted findings change.
504
-
505
- `fix --dry-run` renders safe automatic fix plans without changing files. `fix --interactive --backup` shows the same numbered plan, then applies everything after `yes` or only selected action numbers such as `1,3`. `fix --apply --backup` applies supported safe fixes, such as manifest defaults and missing skills directories, after creating backups.
506
-
507
- Optional local policy file:
508
-
509
- ```json
510
- {
511
- "ignoreRules": ["plugin.heuristic.description.too_long"],
512
- "suppressions": [
513
- {
514
- "fingerprint": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
515
- "reason": "Accepted until the upstream package layout is corrected.",
516
- "expiresAt": "2026-07-31"
517
- }
518
- ],
519
- "failOnWarnings": true
520
- }
521
- ```
522
-
523
- `ignoreRules` disables every finding with a matching rule ID. Prefer `suppressions` when accepting one specific finding instance: each record requires the exact 64-character lowercase SHA-256 fingerprint shown in Doctor reports, a non-empty review reason, and a real `YYYY-MM-DD` expiration date.
524
-
525
- Active suppressions remove only the matching finding from the active result and preserve it under `suppressedFindings` for audit output. Expired or invalid records do not suppress findings; Doctor emits `suppression.expired` or `suppression.invalid` warnings instead. Duplicate active records use the first valid match.
526
-
527
- ### Manage suppressions
528
-
529
- ```bash
530
- codex-plugin-doctor suppress add .
531
- codex-plugin-doctor suppress list .
532
- codex-plugin-doctor suppress remove .
533
- ```
534
-
535
- Interactive add selects one active fingerprinted finding and defaults to an expiration 30 local calendar days from today. The stored `YYYY-MM-DD` record remains active through that UTC calendar date and expires at `00:00 UTC` on the following day. Suppressions match only the exact finding fingerprint; invalid or expired records never hide findings.
536
-
537
- For automation, supply all add fields or one remove selector and add `--json` when machine-readable output is required:
538
-
539
- ```bash
540
- codex-plugin-doctor suppress add . --fingerprint <sha256> --reason "Accepted temporarily." --expires-at 2026-07-31 --json
541
- codex-plugin-doctor suppress list . --json
542
- codex-plugin-doctor suppress remove . --index 0 --json
543
- codex-plugin-doctor suppress remove . --fingerprint <sha256> --json
544
- ```
545
-
546
- Run these when you want Codex Plugin Doctor to find plugins from the local Codex installation:
547
-
548
- ```bash
549
- codex-plugin-doctor list --installed
550
- codex-plugin-doctor check --installed
551
- codex-plugin-doctor check --installed --all-summary
552
- codex-plugin-doctor check --installed --compat --all-summary
553
- codex-plugin-doctor check --installed github
554
- codex-plugin-doctor check --installed github --runtime --no-animations
555
- codex-plugin-doctor explain plugin.security.hard_coded_secret
556
- ```
557
-
558
- ## GitHub Action
559
-
560
- ```yaml
561
- name: Validate Codex plugin
562
-
563
- on:
564
- pull_request:
565
-
566
- jobs:
567
- doctor:
568
- runs-on: ubuntu-latest
569
- steps:
570
- - uses: actions/checkout@v5
571
- - uses: Esquetta/CodexPluginDoctor@v1.69.1
572
- with:
573
- version: "1.69.1"
574
- path: .
575
- runtime: "true"
576
- policy: codex-publish
577
- corpus: "true"
578
- contract: "true"
579
- upload-artifact: "true"
580
- artifact-name: codex-plugin-doctor-reports
581
- review-bundle: "true"
582
- review-bundle-verify: "true"
583
- ```
584
-
585
- The action writes `codex-plugin-doctor-summary.md`, `codex-plugin-doctor-report.json`, `codex-plugin-doctor-action-manifest.json`, optional `codex-plugin-doctor.sarif`, optional validation corpus and quality metrics reports, optional `output-contract.json`, and optional signed `review-bundle/` files to `codex-plugin-doctor-reports`, appends the Markdown report to the GitHub Actions step summary, uploads the report directory as an artifact, and then returns the real validation exit code. Set `submission: "true"` to add offline submission preflight reports; set `require-submission-ready: "true"` only with that opt-in to make automatic blockers fail the job. Review bundle generation requires a signing key environment variable such as `CODEX_PLUGIN_DOCTOR_SIGNING_KEY`. For runtime probing, SARIF output, corpus quality regression gates, corpus and contract artifacts, review bundle artifacts, installed plugin cache checks, CI policy presets, and pinned release examples, see [GitHub Action Usage](./docs/guides/github-action.md).
586
-
587
- To self-test this repository after cloning it:
588
-
589
- ```bash
590
- codex-plugin-doctor check examples/codex-doctor-runtime --runtime --no-animations
591
- ```
592
-
593
- ## Repository Layout
594
-
595
- ```text
596
- docs/ Public architecture, guides, rules, security, and contributor docs
597
- examples/ Manual plugin packs for local CLI testing
598
- src/ CLI, validation logic, runtime probing, reports
599
- tests/ Fixture-based regression tests
600
- ```
601
-
602
- ## Validation Evidence
603
-
604
- The validator is tuned against local fixtures and real marketplace-style plugin packages. See:
605
-
606
- - [Real-World Validation Workflow](./docs/guides/real-world-validation.md)
607
- - [Examples](./examples/README.md)
608
- - [Rule Catalog](./docs/rules/catalog.md)
609
- - [Official Plugin Components](./docs/architecture/official-plugin-components.md)
610
-
611
- Recent validation waves covered:
612
-
613
- - curated Codex plugin cache packages
614
- - marketplace-style plugin snapshots
615
- - YAML block-scalar skill metadata
616
- - media and visual workflow metadata
617
-
618
- ## Release Readiness
619
-
620
- Release preparation is reproducible from the repository:
621
-
622
- ```bash
623
- npm run prepare-release
624
- npm run release-check
625
- ```
626
-
627
- `prepare-release` runs tests, builds the TypeScript output, and performs `npm pack --dry-run`. `release-check` adds release preflight checks for a clean git tree, existing npm versions, existing version tags, package/lockfile/changelog version consistency, tests, build, pack dry-run, fresh temp install audit, and publish dry-run.
628
-
629
- For plugin packages, `codex-plugin-doctor release check .` performs static readiness checks by default. Runtime probing executes package-local MCP servers and therefore requires an explicit `--runtime`; protected workflows can also require the approved runtime-plan digest.
630
-
631
- Related docs:
632
-
633
- - [Changelog](./CHANGELOG.md)
634
- - [Contributing](./CONTRIBUTING.md)
635
- - [Security Policy](./SECURITY.md)
636
- - [Code of Conduct](./CODE_OF_CONDUCT.md)
637
- - [NPM Release Checklist](./docs/contributing/npm-release-checklist.md)
638
- - [Release Candidate Workflow](./docs/contributing/release-candidates.md)
639
- - [Versioning and Releases](./docs/contributing/releasing.md)
640
-
641
- ## Contributing
642
-
643
- Contributions are welcome once the repository is public. Start with:
644
-
645
- - [Contributing](./CONTRIBUTING.md)
646
- - [Security Policy](./SECURITY.md)
647
- - [Validation tuning issue template](./.github/ISSUE_TEMPLATE/validation_tuning.yml)
648
-
649
- ## Support
650
-
651
- If this tool saves you time, GitHub stars and sponsorship help signal that the project is worth continuing.
652
-
653
- - Star the repository on GitHub.
654
- - Use GitHub Sponsors through the repository funding link.
655
- - Open validation tuning issues for false positives or false negatives.
656
-
657
- ## Product Direction
658
-
659
- Codex Plugin Doctor starts as a Codex-specific validator and can grow into a broader MCP Doctor over time.
660
-
661
- The immediate goal is not a marketplace, dashboard, or hosted website. The immediate goal is a trustworthy local preflight check for Codex-compatible plugin bundles.
1
+ # Codex Plugin Doctor
2
+
3
+ [![CI](https://github.com/Esquetta/CodexPluginDoctor/actions/workflows/ci.yml/badge.svg)](https://github.com/Esquetta/CodexPluginDoctor/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/codex-plugin-doctor.svg)](https://www.npmjs.com/package/codex-plugin-doctor)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE)
6
+ [![GitHub release](https://img.shields.io/github/v/release/Esquetta/CodexPluginDoctor)](https://github.com/Esquetta/CodexPluginDoctor/releases)
7
+
8
+ Codex Plugin Doctor is a local CLI validator for Codex plugin packages, skills, and MCP server bundles.
9
+
10
+ It catches packaging, metadata, security, and runtime protocol problems before a plugin reaches users, teammates, or release workflows.
11
+
12
+ ## Status
13
+
14
+ Codex Plugin Doctor is a public stable CLI for local and CI validation.
15
+
16
+ - Primary surface: GitHub repository and npm package
17
+ - Distribution today: `npm install -g`, local source install, `npm link`, `npm pack`, GitHub Releases
18
+ - Public npm package: `codex-plugin-doctor`
19
+ - License: [MIT](./LICENSE)
20
+
21
+ ## 1.0 Stability
22
+
23
+ The 1.0 line is the stable compatibility baseline for plugin authors and CI consumers.
24
+
25
+ - Public JSON schema surfaces and existing rule IDs/default severities are treated as stable through 1.0.
26
+ - Runtime probing remains opt-in because it executes package-local MCP servers.
27
+ - The project remains Codex-first; broader MCP Doctor positioning stays a post-1.0 expansion path.
28
+ - Post-1.0 feature work should stay additive unless a documented major-version decision is made.
29
+
30
+ See the [documentation index](./docs/README.md) for architecture, usage, security, and contributor guides.
31
+
32
+ ## Why This Exists
33
+
34
+ Codex plugin packages can fail in several places:
35
+
36
+ - the package manifest is missing or points outside the package root
37
+ - skills exist but do not expose valid `SKILL.md` metadata
38
+ - `.mcp.json` is malformed or references unsafe secrets
39
+ - an MCP server starts but does not complete the protocol handshake
40
+ - tools, resources, or prompts list successfully but fail deeper runtime checks
41
+ - verbose metadata creates noisy matching and unnecessary context cost
42
+
43
+ This tool gives plugin authors a repeatable preflight check before distribution.
44
+
45
+ ## What It Checks
46
+
47
+ Static validation:
48
+
49
+ - required `.codex-plugin/plugin.json`
50
+ - manifest fields: `name`, `version`, `description`
51
+ - skill directory wiring
52
+ - `SKILL.md` presence and frontmatter fields
53
+ - YAML single-line and block-scalar skill descriptions
54
+ - `.mcp.json` structure
55
+ - path traversal risks
56
+ - hard-coded secret-like env values
57
+ - description quality heuristics tuned against real plugin packages
58
+
59
+ Security scorecard with `security`:
60
+
61
+ - shell wrapper command warnings for MCP servers
62
+ - encoded shell command failures
63
+ - remote content piped into shell failures
64
+ - MCP server `cwd` paths that escape the package root
65
+ - plain HTTP remote transport warnings
66
+
67
+ Runtime MCP validation with `--runtime`:
68
+
69
+ - `initialize`
70
+ - `notifications/initialized`
71
+ - `tools/list`
72
+ - `tools/call`
73
+ - `resources/list`
74
+ - `resources/read`
75
+ - `resources/templates/list`
76
+ - `prompts/list`
77
+ - `prompts/get`
78
+ - paginated list responses
79
+ - runtime capability scorecard
80
+ - redacted verbose transcript with `--verbose-runtime`
81
+ - optional runtime approval gating with a precomputed `doctor runtime-plan` digest
82
+ - optional Docker isolation for local Node.js stdio servers with `--sandbox docker`
83
+
84
+ ### MCP Protocol Discovery
85
+
86
+ Inspect an HTTP MCP endpoint's advertised protocol versions using a bounded MCP
87
+ 2026-07-28 `server/discover` request:
88
+
89
+ ```bash
90
+ codex-plugin-doctor doctor discover https://mcp.example.com/mcp --allow-network
91
+ codex-plugin-doctor doctor discover https://mcp.example.com/mcp --allow-network --json
92
+ ```
93
+
94
+ This is an opt-in discovery-only check. A successful result validates the discovery
95
+ response, not full protocol conformance, tool behavior, or compatibility with a
96
+ particular client. Existing `check --runtime` remains on its 2025-11-25 baseline.
97
+ See [MCP Discovery](docs/guides/mcp-discovery.md) for consent, scope, and exit codes.
98
+
99
+ ### Offline MCP Tool Definitions
100
+
101
+ Inspect a saved MCP 2026-07-28 `tools/list` response without contacting a server:
102
+
103
+ ```bash
104
+ codex-plugin-doctor doctor tools-file ./tools-list.json --json
105
+ ```
106
+
107
+ This checks the supplied tool definitions and root-schema shapes within fixed file,
108
+ tool, and finding limits. It does not establish server inventory completeness or
109
+ execute tools. See [Offline MCP Tool Definitions](docs/guides/offline-tool-definitions.md)
110
+ for the accepted input format, coverage, and exit codes.
111
+
112
+ ### Offline MCP Tool Diff
113
+
114
+ Compare two saved tool-list responses before updating a server or client:
115
+
116
+ ```bash
117
+ codex-plugin-doctor doctor tools-diff --before ./tools-old.json --after ./tools-new.json --json
118
+ ```
119
+
120
+ This reports added, removed, and structurally changed definitions using numeric
121
+ locations, and labels each change `breaking`, `compatible`, or `unclassified`
122
+ with fixed reason codes. Add `--fail-on breaking` to fail CI only on breaking or
123
+ unclassified changes, and `--markdown` for pull request tables. Incomplete inputs, invalid definitions, or duplicate names
124
+ prevent a comparison. Impact labels follow nested object properties, array
125
+ items, and common length and range bounds, but remain heuristics, not proof of
126
+ compatibility.
127
+ See [Offline MCP Tool Diff](docs/guides/offline-tool-diff.md) for matching rules,
128
+ privacy, limits, and exit codes.
129
+
130
+ ### MCP Tool Catalog
131
+
132
+ Inspect a modern HTTP MCP server's tool definitions without invoking them:
133
+
134
+ ```bash
135
+ codex-plugin-doctor doctor tools https://mcp.example.com/mcp --allow-network --json
136
+ ```
137
+
138
+ This opt-in command performs discovery and bounded `tools/list` pagination. It
139
+ reports tool-definition and root-schema shape findings, explicit completion state,
140
+ and partial inspection limits. It does not claim full schema validation, tool
141
+ execution, or client compatibility. Existing `doctor discover` behavior is unchanged.
142
+ Add `--save-response <path>` to record a completely enumerated catalog as a
143
+ `tools/list` response for `tools-file` and `tools-diff`; nothing is written when
144
+ enumeration is incomplete. For protected servers, `--bearer-token-env <NAME>`
145
+ sends a bearer token from an environment variable only over HTTPS or to an
146
+ approved loopback endpoint; it is never printed or saved. The GitHub Action can compare saved responses with
147
+ `tools-diff-before`, `tools-diff-after`, and `tools-diff-fail-on`, capture the
148
+ live list with `tools-capture-url` (and `tools-capture-token-env`) or, for a local
149
+ stdio server with `runtime: "true"`, `tools-capture-server`, and skip the
150
+ plugin package check with `check: "false"` in repositories that only ship an MCP
151
+ server.
152
+
153
+ Local stdio servers from a package's MCP configuration can be cataloged too.
154
+ `--runtime` is required because this starts package code; the server is stopped
155
+ after its tool list is read:
156
+
157
+ ```bash
158
+ codex-plugin-doctor doctor tools ./my-plugin --server my-server --runtime --save-response ./tools-current.json
159
+ ```
160
+
161
+ Doctor tries `server/discover` (`2026-07-28`) first and falls back to the
162
+ `initialize` handshake for older stdio servers, so the saved list works with
163
+ `tools-file` and `tools-diff` either way. `--sandbox docker` and
164
+ `--require-runtime-approval` work as they do for `check --runtime`.
165
+ See [MCP Tool Catalog](docs/guides/mcp-tool-catalog.md).
166
+
167
+ ### Remote MCP Readiness
168
+
169
+ Remote MCP runtime probing is disabled until you explicitly pass `--runtime --allow-network`. Loopback endpoints also require `--allow-local-network`:
170
+
171
+ ```bash
172
+ codex-plugin-doctor check ./remote-mcp --runtime --allow-network
173
+ codex-plugin-doctor check ./remote-mcp --runtime --allow-network --allow-local-network
174
+ ```
175
+
176
+ The probe makes only bounded protocol and OAuth metadata-discovery requests, redacts report output, and applies SSRF controls. It does not authenticate or follow redirects.
177
+
178
+ Remote transport reliability adds one bounded SSE GET after initialization. HTTP `200` must be `text/event-stream`; HTTP `405` is compliant when the endpoint does not offer server-to-client SSE. At most one SSE resume and one session restart are attempted, and no remote response content is retained. This is a bounded readiness check, not a live interoperability, delivery-guarantee, or load-test claim.
179
+
180
+ `--allow-session-lifecycle` is disabled by default and is state-changing: only after a valid `MCP-Session-Id` it permits one bounded session `DELETE`. `--require-remote-reliability` is a strict result gate: it fails unless every attempted remote reliability scorecard passes. Local-only runs are unaffected. It grants no network consent, so `--runtime --allow-network` (and loopback consent when applicable) remain required. See [Remote MCP Readiness](./docs/architecture/remote-mcp-readiness.md) and [Remote MCP Transport Reliability](./docs/architecture/remote-mcp-transport-reliability.md).
181
+
182
+ ### MCP Registry Readiness
183
+
184
+ Validate official MCP Registry publication metadata without publishing or installing anything:
185
+
186
+ ```bash
187
+ codex-plugin-doctor registry check path/to/server.json
188
+ codex-plugin-doctor registry check path/to/server.json --json --require-registry-readiness
189
+ codex-plugin-doctor registry inspect io.github.example/weather --allow-network
190
+ ```
191
+
192
+ Local checks validate metadata, ownership consistency, package integrity, transports, and Codex installability. Exact Registry lookup is read-only, requires explicit network consent, and contacts only the fixed official Registry endpoint. It never follows advertised package, icon, repository, or remote MCP URLs. See [MCP Registry Readiness](./docs/architecture/mcp-registry-readiness.md).
193
+
194
+ ### MCP Registry Publication Preflight
195
+
196
+ Check a publication candidate locally without making a network request:
197
+
198
+ ```bash
199
+ codex-plugin-doctor registry preflight path/to/server.json --json
200
+ ```
201
+
202
+ Opt in to bounded public npm and MCP Registry metadata checks:
203
+
204
+ ```bash
205
+ codex-plugin-doctor registry preflight path/to/server.json --allow-network --json
206
+ ```
207
+
208
+ Require a publish-ready result in CI:
209
+
210
+ ```bash
211
+ codex-plugin-doctor registry preflight path/to/server.json --allow-network --require-publish-ready --json
212
+ ```
213
+
214
+ Preflight checks the exact npm package version, then the exact Registry version
215
+ and latest Registry record on fixed public hosts. An existing exact Registry
216
+ version is an immutable collision and must be replaced by a version bump. The
217
+ command is advisory: it never authenticates, publishes, or changes npm or
218
+ Registry records. See [MCP Registry Publication Preflight](./docs/architecture/mcp-registry-publication-preflight.md).
219
+
220
+ ### Public Directory Submission Preflight
221
+
222
+ Check a plugin package for deterministic public-directory submission issues without contacting a portal:
223
+
224
+ ```bash
225
+ codex-plugin-doctor doctor submission <path>
226
+ codex-plugin-doctor doctor submission <path> --json
227
+ codex-plugin-doctor doctor submission <path> --markdown
228
+ codex-plugin-doctor doctor submission <path> --require-ready
229
+ codex-plugin-doctor doctor submission archive <zip>
230
+ codex-plugin-doctor doctor submission archive <zip> --json --output submission-archive.json
231
+ codex-plugin-doctor doctor submission archive <zip> --markdown --output submission-archive.md
232
+ codex-plugin-doctor doctor submission archive <zip> --require-ready
233
+ ```
234
+
235
+ The preflight is offline and non-executing: it does not submit a package, make network requests, start MCP servers, verify domains, or handle OAuth credentials. Its automatic `status` is `pass` or `fail`; a passing automatic result remains `manual_review_required` until portal-only review is complete. It never claims directory acceptance. See [Public Directory Submission Preflight](./docs/architecture/public-directory-submission-preflight.md).
236
+
237
+ The archive variant accepts an existing skills-only ZIP and does not extract archive entries to disk, execute package code, or repair the archive. It reports malformed ZIP structures and deterministic package blockers; unsupported portal rules remain manual or `coverage: unavailable` rather than an automatic pass.
238
+
239
+ Output formats:
240
+
241
+ - human text output
242
+ - JSON reports
243
+ - Markdown reports
244
+ - Shields-compatible badge JSON and static badge Markdown
245
+ - validation history JSONL and trend summaries
246
+ - deterministic local attestation artifacts
247
+ - output contract and rule catalog freeze metadata
248
+ - bundled validation corpus reports
249
+ - `--output` file writing
250
+ - CI summary and artifact generation
251
+
252
+ ## Quick Start
253
+
254
+ Global install from npm:
255
+
256
+ ```bash
257
+ npm install -g codex-plugin-doctor
258
+ codex-plugin-doctor --version
259
+ codex-plugin-doctor self-test
260
+ codex-plugin-doctor check path/to/plugin-package
261
+ ```
262
+
263
+ Run `codex-plugin-doctor check .` from the root of a Codex plugin package that contains `.codex-plugin/plugin.json`. The Codex Plugin Doctor source repository is not itself a plugin package.
264
+
265
+ If you already have Codex installed locally and do not know plugin paths, discover the installed plugin cache:
266
+
267
+ ```bash
268
+ codex-plugin-doctor list --installed
269
+ codex-plugin-doctor check --installed
270
+ codex-plugin-doctor check --installed --all-summary
271
+ codex-plugin-doctor check --installed --compat --all-summary
272
+ codex-plugin-doctor audit --installed --security --compat
273
+ codex-plugin-doctor audit --installed --security --compat --policy security
274
+ codex-plugin-doctor mcp path/to/mcp-package
275
+ codex-plugin-doctor check --installed github
276
+ codex-plugin-doctor explain plugin.manifest.missing
277
+ ```
278
+
279
+ Run from source:
280
+
281
+ ```bash
282
+ npm install
283
+ npm run build
284
+ node dist/cli.js check examples/codex-doctor-runtime --runtime
285
+ ```
286
+
287
+ For local global usage:
288
+
289
+ ```bash
290
+ npm link
291
+ codex-plugin-doctor check examples/codex-doctor-runtime --runtime
292
+ ```
293
+
294
+ Generate validation artifacts locally:
295
+
296
+ ```bash
297
+ npm run generate-validation-artifacts -- --target examples/codex-doctor-runtime --runtime-target examples/codex-doctor-runtime --out-dir validation-artifacts-local
298
+ ```
299
+
300
+ ## Example Output
301
+
302
+ Passing runtime package:
303
+
304
+ ```text
305
+ Codex Plugin Doctor
306
+ ===================
307
+ Status: PASS
308
+ Target: <repo>\examples\codex-doctor-runtime
309
+ Summary: 0 fail, 0 warn, 0 total
310
+
311
+ Runtime Scorecard
312
+ ----------------
313
+ initialize: pass
314
+ tools/list: pass
315
+ tools/call: pass
316
+ resources/list: pass
317
+ resources/read: pass
318
+ resources/templates/list: pass
319
+ prompts/list: pass
320
+ prompts/get: pass
321
+
322
+ No findings.
323
+ ```
324
+
325
+ Risky package:
326
+
327
+ ```text
328
+ Codex Plugin Doctor
329
+ ===================
330
+ Status: FAIL
331
+ Target: <repo>\examples\codex-doctor-risky
332
+ Summary: 1 fail, 0 warn, 1 total
333
+
334
+ Failures
335
+ --------
336
+ x plugin.security.hard_coded_secret
337
+ Message: The MCP server `dangerServer` contains a hard-coded secret-like env value for `OPENAI_API_KEY`.
338
+ Impact: Hard-coded credentials inside plugin bundles increase leakage risk and make secure rotation difficult.
339
+ Suggested fix: Replace the literal value for `OPENAI_API_KEY` with an environment reference or injected secret outside the package.
340
+ ```
341
+
342
+ ## Useful Commands
343
+
344
+ Run these from a Codex plugin package root:
345
+
346
+ ```bash
347
+ codex-plugin-doctor --version
348
+ codex-plugin-doctor self-test
349
+ codex-plugin-doctor doctor
350
+ codex-plugin-doctor doctor contract
351
+ codex-plugin-doctor doctor contract --json --output output-contract.json
352
+ codex-plugin-doctor doctor corpus
353
+ codex-plugin-doctor doctor corpus --json --output validation-corpus.json
354
+ codex-plugin-doctor doctor corpus --manifest ../private-corpus/corpus.json --json
355
+ codex-plugin-doctor doctor corpus metrics --manifest ../private-corpus/metrics.json --markdown
356
+ codex-plugin-doctor doctor corpus metrics --manifest ../private-corpus/metrics.json --json --min-precision 0.90 --min-recall 0.85 --max-false-positive-rate 0.10
357
+ codex-plugin-doctor doctor npm <published-plugin-package>
358
+ codex-plugin-doctor doctor npm <published-plugin-package> --json --output npm-preinstall.json
359
+ codex-plugin-doctor doctor attest .
360
+ codex-plugin-doctor doctor attest . --json --output attestation.json
361
+ codex-plugin-doctor doctor attest . --json --sign-key-env CODEX_PLUGIN_DOCTOR_SIGNING_KEY --output attestation.json
362
+ codex-plugin-doctor doctor attest verify attestation.json --target . --sign-key-env CODEX_PLUGIN_DOCTOR_SIGNING_KEY
363
+ codex-plugin-doctor doctor attest verify attestation.json --target . --json --sign-key-env CODEX_PLUGIN_DOCTOR_SIGNING_KEY
364
+ codex-plugin-doctor doctor inspector .
365
+ codex-plugin-doctor doctor inspector . --server context7 --json --output inspector-command.json
366
+ codex-plugin-doctor doctor diff --before ./old-plugin --after ./new-plugin
367
+ codex-plugin-doctor doctor diff --before ./old-plugin --after ./new-plugin --json --output risk-diff.json
368
+ codex-plugin-doctor doctor recommend .
369
+ codex-plugin-doctor doctor recommend . --json --output recommendations.json
370
+ codex-plugin-doctor doctor trust .
371
+ codex-plugin-doctor doctor trust . --json --output trust-score.json
372
+ codex-plugin-doctor doctor perf .
373
+ codex-plugin-doctor doctor perf . --json --output perf.json
374
+ codex-plugin-doctor doctor perf . --max-total-ms 2500 --max-stage-ms validation=500
375
+ codex-plugin-doctor doctor runtime-plan .
376
+ codex-plugin-doctor doctor runtime-plan . --json --output runtime-plan.json
377
+ codex-plugin-doctor doctor runtime-plan . --markdown --output runtime-plan.md
378
+ codex-plugin-doctor doctor runtime-plan . --sandbox docker --json
379
+ codex-plugin-doctor doctor runtime-policy .
380
+ codex-plugin-doctor doctor runtime-policy . --json --output runtime-policy.json
381
+ codex-plugin-doctor doctor runtime-policy . --sandbox docker --json
382
+ codex-plugin-doctor doctor review-bundle . --output review-bundle --sign-key-env CODEX_PLUGIN_DOCTOR_SIGNING_KEY
383
+ codex-plugin-doctor doctor review-bundle verify review-bundle --target . --sign-key-env CODEX_PLUGIN_DOCTOR_SIGNING_KEY
384
+ codex-plugin-doctor doctor review-bundle diff --before old-review-bundle --after review-bundle
385
+ codex-plugin-doctor doctor mcp .
386
+ codex-plugin-doctor doctor mcp . --json --output mcp-healthcheck.json
387
+ codex-plugin-doctor doctor export --bundle .
388
+ codex-plugin-doctor doctor export --bundle . --output doctor-bundle.json
389
+ codex-plugin-doctor doctor snapshot
390
+ codex-plugin-doctor doctor snapshot --json
391
+ codex-plugin-doctor doctor snapshot --output doctor-snapshot.json
392
+ codex-plugin-doctor doctor clients
393
+ codex-plugin-doctor doctor --update-check
394
+ codex-plugin-doctor audit --installed
395
+ codex-plugin-doctor audit --installed --security --compat
396
+ codex-plugin-doctor audit --installed --security --compat --json --output local-audit.json
397
+ codex-plugin-doctor audit --installed --security --compat --cache
398
+ codex-plugin-doctor audit --installed --changed --cache
399
+ codex-plugin-doctor audit deps .
400
+ codex-plugin-doctor audit deps . --json --output dependency-audit.json
401
+ codex-plugin-doctor audit deps . --recommend
402
+ codex-plugin-doctor audit deps . --recommend --json --output dependency-remediation.json
403
+ codex-plugin-doctor watch .
404
+ codex-plugin-doctor watch . --json --output watch-latest.json --debounce-ms 500
405
+ codex-plugin-doctor init-git-hooks .
406
+ codex-plugin-doctor init-git-hooks . --json
407
+ codex-plugin-doctor mcp .
408
+ codex-plugin-doctor mcp . --json
409
+ codex-plugin-doctor mcp . --json --output mcp-doctor.json
410
+ codex-plugin-doctor init my-plugin
411
+ codex-plugin-doctor init my-mcp --template mcp-stdio
412
+ codex-plugin-doctor init remote-mcp --template mcp-http
413
+ codex-plugin-doctor init runtime-demo --template full-runtime
414
+ codex-plugin-doctor security .
415
+ codex-plugin-doctor security . --scorecard
416
+ codex-plugin-doctor security . --json
417
+ codex-plugin-doctor security . --policy security
418
+ codex-plugin-doctor compat .
419
+ codex-plugin-doctor compat . --all --scorecard
420
+ codex-plugin-doctor compat . --client codex
421
+ codex-plugin-doctor compat . --client generic-mcp
422
+ codex-plugin-doctor compat . --client claude-desktop
423
+ codex-plugin-doctor compat . --client claude-desktop --install-preview
424
+ codex-plugin-doctor compat . --client claude-desktop --apply --backup
425
+ codex-plugin-doctor compat . --client cursor
426
+ codex-plugin-doctor compat . --client cursor --install-preview
427
+ codex-plugin-doctor compat . --client cursor --apply --backup
428
+ codex-plugin-doctor compat . --client cline
429
+ codex-plugin-doctor compat . --client cline --install-preview
430
+ codex-plugin-doctor compat . --scorecard
431
+ codex-plugin-doctor compat . --json
432
+ codex-plugin-doctor compat . --json --output compatibility.json
433
+ codex-plugin-doctor check .
434
+ codex-plugin-doctor check . --profile ci
435
+ codex-plugin-doctor check . --profile strict
436
+ codex-plugin-doctor check . --profile publish
437
+ codex-plugin-doctor check . --policy codex-publish
438
+ codex-plugin-doctor check . --policy mcp-strict
439
+ codex-plugin-doctor check . --policy security
440
+ codex-plugin-doctor check . --json
441
+ codex-plugin-doctor check . --explain
442
+ codex-plugin-doctor check . --json --output report.json
443
+ codex-plugin-doctor check . --markdown --output report.md
444
+ codex-plugin-doctor check . --badge-json --output doctor-badge.json
445
+ codex-plugin-doctor check . --badge-markdown
446
+ codex-plugin-doctor check . --sarif --output results.sarif
447
+ codex-plugin-doctor check . --ascii
448
+ codex-plugin-doctor check . --no-animations
449
+ codex-plugin-doctor check . --runtime
450
+ codex-plugin-doctor check . --runtime --require-runtime-approval --runtime-approval-digest sha256:<approved-plan-digest>
451
+ codex-plugin-doctor check . --runtime --sandbox docker
452
+ codex-plugin-doctor check . --runtime --sandbox docker --require-runtime-approval --runtime-approval-digest sha256:<approved-docker-plan-digest>
453
+ codex-plugin-doctor release check .
454
+ codex-plugin-doctor release check . --json
455
+ codex-plugin-doctor release check . --runtime
456
+ codex-plugin-doctor release check . --runtime --require-runtime-approval --runtime-approval-digest sha256:<approved-plan-digest>
457
+ codex-plugin-doctor release check . --runtime --sandbox docker --require-runtime-approval --runtime-approval-digest sha256:<approved-docker-plan-digest>
458
+ codex-plugin-doctor check . --config .codex-doctor.json
459
+ codex-plugin-doctor baseline create . --output .codex-doctor-baseline.json
460
+ codex-plugin-doctor check . --baseline .codex-doctor-baseline.json
461
+ codex-plugin-doctor check . --history validation-history.jsonl
462
+ codex-plugin-doctor history validation-history.jsonl
463
+ codex-plugin-doctor history validation-history.jsonl --json
464
+ codex-plugin-doctor history validation-history.jsonl --fail-on-regression
465
+ codex-plugin-doctor fix . --dry-run
466
+ codex-plugin-doctor fix . --interactive --backup
467
+ codex-plugin-doctor fix . --apply --backup
468
+ codex-plugin-doctor check . --json --runtime --verbose-runtime
469
+ ```
470
+
471
+ Docker runtime mode supports local Node.js stdio MCP servers. It uses a digest-pinned image, no network, read-only container and package filesystems, an unprivileged user, dropped capabilities, bounded resources, and a limited writable `/tmp`. It fails closed without native fallback and rejects package roots containing commas. The Docker daemon, base image, and host kernel remain trusted boundaries. Generate approval digests with the same `--sandbox docker` backend used for execution. See [Runtime Approval And Sandboxing](./docs/security/runtime-approval-and-sandboxing.md).
472
+
473
+ External corpus evaluation is static and offline. `doctor corpus --manifest <corpus.json>` validates anonymized local snapshots using stable content digests and exact finding fingerprints without downloading dependencies or starting target servers. Reports omit manifest and package paths and fail on digest drift, missing expected findings, present disputed findings, or unreviewed findings. See [Real-World Validation](./docs/guides/real-world-validation.md).
474
+
475
+ `doctor corpus metrics --manifest <corpus.json>` measures reviewed true positives, false positives, and false negatives as precision, recall, and emitted-finding false-positive share. Optional thresholds make the measurement release-gating; incomplete reviews and digest drift return exit `2` instead of producing a favorable score. The dedicated metrics manifest stays offline, requires contained snapshot paths, and may record immutable HTTPS Git provenance without fetching it.
476
+
477
+ `doctor corpus metrics diff --before <metrics.json> --after <metrics.json>` compares two complete metrics reports from the same corpus identity. Add `--fail-on-regression` to fail CI when precision or recall decreases, or when the reviewed emitted-finding false-positive share increases. Reports with different `corpusDigest` values are rejected as non-comparable, and diff output never includes the input report paths.
478
+
479
+ `self-test` runs the bundled runtime-complete sample through static validation, runtime MCP probes, and the compatibility scorecard. It is the fastest post-install check after `npm install -g codex-plugin-doctor`.
480
+
481
+ `doctor` checks the local environment, including package version, platform, Node version, npm global prefix, Codex home, and Codex plugin cache visibility. The text output also includes recommended next commands for self-test, installed plugin discovery, runtime checks, compatibility scoring, and CI setup. `doctor contract` publishes the machine-readable output contract, including public JSON schema surfaces, stable-through-1.0 compatibility metadata, and a frozen rule catalog digest. Add `--json` for automation or `--output output-contract.json` to write the contract to disk. `doctor corpus` runs the bundled validation corpus against healthy runtime, risky security, starter skill, and generic MCP packages, then reports whether each case matched its expected outcome. Add `--json` for automation or `--output validation-corpus.json` to write the corpus report to disk. `doctor npm <package>` runs a preinstall scan by packing the npm package with scripts disabled, extracting the publish tarball, and running validation, security, trust, and recommendation checks against the shipped contents. The JSON report includes tarball metadata such as filename, path, integrity, shasum, sizes, file count, and extracted package root so automation can prove which archive was scanned. Use a published Codex plugin package as the target; scanning `codex-plugin-doctor` itself intentionally reports a missing plugin manifest because this CLI package is not a plugin package. Add `--json` for automation or `--output npm-preinstall.json` to write the report to disk. `doctor attest <path>` creates a local attestation with stable package/report digests, validation/security/compatibility/trust summary, and verification metadata. Add `--sign-key-env NAME` to attach a local HMAC-SHA256 signature without printing the secret, or `--json --output attestation.json` to write the artifact to disk. `doctor attest verify <attestation.json> --target <path> --sign-key-env NAME` recomputes the package fingerprint, report digest, and HMAC signature offline; verification intentionally treats `generatedAt`, `targetPath`, `verification`, and `signature.keyHint` as unsigned display metadata. `doctor runtime-plan <path>` creates a non-executing runtime plan that lists MCP server commands, safe probe methods, risk reasons, and a stable approval digest before any local server is started. Add `--markdown --output runtime-plan.md` to preserve a review-ready approval artifact with the execution boundary, checklist, servers, probes, and risk reasons. `doctor runtime-policy <path>` evaluates the same runtime plan and security signals, then recommends `allow`, `review`, `sandbox_recommended`, or `deny` before local MCP execution starts. `doctor review-bundle <path> --output <dir> --sign-key-env NAME` writes a signed review directory with runtime plan, runtime policy, attestation, release evidence, manifest, Markdown summary files, and SHA-256 file integrity digests. `doctor review-bundle verify <bundle-dir> --target <path> --sign-key-env NAME` verifies the bundle manifest, expected files, manifest integrity digests, runtime artifacts, signed attestation, and signed release evidence offline before a reviewer trusts the handoff. `doctor review-bundle diff --before <dir> --after <dir>` compares two review bundles and flags risk-increasing changes in status, runtime policy, release readiness, signatures, release evidence, and runtime plan digest. `check --runtime --require-runtime-approval --runtime-approval-digest <digest>` refuses to run runtime probes unless the current plan digest matches the approved digest. `doctor release-evidence <path> --sign-key-env NAME` creates one redacted release bundle with signed attestation, offline verification, corpus, performance, security, trust, package metadata, git release gates, and runtime approval status. Strict release evidence requires a clean tagged worktree; use `--allow-dirty` or `--allow-untagged` only for local rehearsal. `doctor release-evidence verify <evidence.json> --target <path> --sign-key-env NAME` verifies a shared release evidence artifact offline against an explicit package path; the artifact target path is treated as display metadata, not trusted input. `doctor release-evidence asset <path> --tag <tag> --output <evidence.json> --sign-key-env NAME` writes a signed release evidence file and prints the `gh release upload` command; add `--upload` to run the upload through GitHub CLI with `--clobber`. `doctor inspector <path>` builds a safe MCP Inspector launch command from a packaged `.mcp.json` file without starting the Inspector proxy automatically. Use `--server <name>` when the package contains multiple MCP server entries. `doctor diff --before <path> --after <path>` compares two package roots and reports new findings, resolved findings, trust score delta, and whether risk increased. `doctor recommend <path>` turns validation, security, and compatibility signals into a prioritized action plan with blocker, high, medium, and info actions. Add `--json` for automation or `--output recommendations.json` to write the report to disk. `doctor trust <path>` creates a local trust score from package lifecycle scripts, dependency specs, and MCP security findings. Use it before release when you want supply-chain risks summarized as one score. `doctor perf <path>` profiles the shared package analysis pipeline and reports per-stage durations for validation, config, security, compatibility, trust, recommendations, and total runtime. Add `--max-total-ms <ms>` or repeatable `--max-stage-ms stage=ms` to fail CI when a budget is exceeded. `doctor mcp <path>` exposes the generic MCP static health report under the doctor command family without starting local MCP servers. `doctor export --bundle <path>` creates a redacted operator handoff bundle that includes validation JSON, security scorecard data, compatibility matrix, recommendations, and trust score in one file. `doctor snapshot` creates a redacted diagnostics bundle with environment health, client config readiness, installed plugin metadata, and next commands. Add `--json` for machine-readable output or `--output doctor-snapshot.json` to write the bundle to disk. `doctor clients` reports local Codex, Claude Desktop, Cursor, Cline, and Windsurf config readiness. `doctor --update-check` compares the installed CLI version with the latest npm version and prints the upgrade command when a newer release is available.
482
+
483
+ `audit --installed` runs a local ecosystem audit against every discovered Codex plugin in the installed plugin cache. Add `--security` to include security scorecards, `--compat` to include the all-client compatibility matrix, and `--json --output local-audit.json` when you want a shareable machine-readable report. Add `--cache` to reuse unchanged plugin results between runs; add `--changed` to only report plugins whose fingerprint changed since the last cached audit. Use `--cache-file path/to/audit-cache.json` when CI or scripted runs need an explicit cache location.
484
+
485
+ `audit deps <path>` runs `npm audit --json` for the target package and normalizes dependency vulnerability results into a stable `schemaVersion: "1.0.0"` report. Use `--json --output dependency-audit.json` when CI needs machine-readable status, vulnerability counts, and the raw npm audit payload. Add `--recommend` to include prioritized remediation actions for direct upgrades, direct no-fix packages, transitive parent updates, and manual transitive review.
486
+
487
+ `watch <path>` continuously validates a plugin package after file changes. Use `--debounce-ms <ms>` to tune noisy repositories, `--runtime` when runtime probes are required, and `--json --output watch-latest.json` when another process should consume the latest validation snapshot.
488
+
489
+ `init-git-hooks [path]` installs generated pre-commit and pre-push hooks that run Codex Plugin Doctor validation before local commits and pushes. Add `--force` to overwrite existing hooks and `--json` when setup automation needs the written hook paths.
490
+
491
+ `--policy codex-publish|mcp-strict|security` applies opinionated gates without requiring a local `.codex-doctor.json`. `codex-publish` fails warnings and enables runtime probes for release checks, `mcp-strict` does the same for MCP-heavy packages, and `security` fails warning-level security findings so advisory risks can block a local audit or CI gate.
492
+
493
+ `mcp <path>` diagnoses generic MCP packages that may not have a Codex plugin manifest. It looks for `.mcp.json` or a manifest `mcpServers` reference, validates the top-level `mcpServers` object and server transports, adds MCP command-surface security findings, and includes the all-client compatibility matrix in the same report.
494
+
495
+ `init [path] --template ...` creates targeted starter packages. `skill-only` is the default minimal skill package, `mcp-stdio` adds a local stdio MCP config and mock server, `mcp-http` scaffolds a streamable HTTP MCP config, and `full-runtime` generates a stdio sample that passes the runtime protocol probes.
496
+
497
+ `security <path>` renders a focused package security scorecard. It reuses the existing package security findings, then adds deeper MCP command-surface checks for shell wrappers, encoded shell payloads, remote pipe-to-shell startup patterns, `cwd` values outside the plugin root, and plain HTTP URLs. Findings include structured, instance-specific evidence such as manifest fields, skill paths, server names, protocol methods, dependency sections, env keys, and bounded payload lengths. Deterministic SHA-256 fingerprints derive from the rule ID and canonical evidence, with package paths normalized for cross-machine stability. Secrets, prompt bodies, resource contents, tool payloads, stderr, and encoded commands are not copied into evidence. Use `--json` for automation or `--scorecard` for a compact status view.
498
+
499
+ `compat --client claude-desktop` checks whether the MCP package can be added to the local Claude Desktop setup. On Windows it looks for `%APPDATA%\Claude\claude_desktop_config.json`; on macOS it looks for `~/Library/Application Support/Claude/claude_desktop_config.json`. A valid existing config returns `PASS`, a missing Claude Desktop install returns `WARN`, and a malformed local config returns `FAIL` so you do not add new servers into a broken config file. If the package server name already exists in Claude Desktop, the command returns `WARN` with the duplicate server name. Add `--install-preview` to print the JSON snippet that should be merged into `claude_desktop_config.json`; it does not modify files. Use `--apply --backup` only when you want the CLI to create a timestamped backup and merge the server config. Apply mode refuses to overwrite duplicate server names.
500
+
501
+ `compat --client cursor` checks whether the MCP package can be added to Cursor. It prefers a project-level `.cursor/mcp.json` when one already exists in the target package, then falls back to the global `~/.cursor/mcp.json` path. A valid existing config returns `PASS`, a missing Cursor config returns `WARN`, malformed JSON returns `FAIL`, and duplicate MCP server names return `WARN`. Add `--install-preview` to print the JSON snippet that should be merged into Cursor's `mcp.json`; it does not modify files. Use `--apply --backup` only when you want the CLI to create a timestamped backup and merge the server config. Apply mode refuses to overwrite duplicate server names.
502
+
503
+ `compat --client cline` checks whether the MCP package can be added to Cline. It uses `CLINE_DIR/data/settings/cline_mcp_settings.json` when `CLINE_DIR` is set, otherwise `~/.cline/data/settings/cline_mcp_settings.json`. Add `--install-preview` to print the JSON snippet that should be merged into `cline_mcp_settings.json`.
504
+
505
+ `compat --all` makes the all-client matrix explicit when you want Codex, Generic MCP, Claude Desktop, Cursor, Cline, and Windsurf in one run. `compat --scorecard` turns the compatibility matrix into a compact score summary. `PASS` maps to `100`, `WARN` maps to `70`, and `FAIL` or `SKIPPED` maps to `0`.
506
+
507
+ `check --installed --compat --all-summary` validates every discovered Codex plugin from the local plugin cache and appends a compact compatibility summary for Codex, Generic MCP, Claude Desktop, Cursor, Cline, and Windsurf. This is the fastest repo-free audit when a user does not know individual plugin paths.
508
+
509
+ `check --profile ci|strict|publish` applies named validation policies. `ci` keeps default behavior, `strict` fails on warnings, and `publish` fails on warnings while enabling runtime probing by default.
510
+
511
+ `check --explain` adds a deduplicated `Next Actions` summary plus inline rule catalog context to text reports, including the problem summary, rule category, why a finding matters, a more detailed fix path, a compact example, and the matching `codex-plugin-doctor explain <finding-id>` follow-up command.
512
+
513
+ `check --badge-json` emits Shields endpoint-compatible JSON such as `{"schemaVersion":1,"label":"doctor","message":"PASS","color":"brightgreen"}`. `check --badge-markdown` emits a static shields.io Markdown badge for README or release notes. Badge output is intentionally limited to single package checks, not `check --installed`.
514
+
515
+ `check --history <path>` appends a compact JSONL validation snapshot after a single package check. `history <path>` reads the JSONL file and compares the latest run to the previous run, including status, finding-count deltas, and whether the latest run regressed. Add `history --json` for automation output or `history --fail-on-regression` when CI should fail after a worse latest run.
516
+
517
+ `baseline create <path> --output <path>` records the current fingerprinted findings for gradual CI adoption. A later `check <path> --baseline <path>` keeps matched findings visible in baseline metadata but gates only new active findings; reports summarize new, matched, and resolved counts. Commit the baseline for review and regenerate it deliberately after accepted findings change.
518
+
519
+ `fix --dry-run` renders safe automatic fix plans without changing files. `fix --interactive --backup` shows the same numbered plan, then applies everything after `yes` or only selected action numbers such as `1,3`. `fix --apply --backup` applies supported safe fixes, such as manifest defaults and missing skills directories, after creating backups.
520
+
521
+ Optional local policy file:
522
+
523
+ ```json
524
+ {
525
+ "ignoreRules": ["plugin.heuristic.description.too_long"],
526
+ "suppressions": [
527
+ {
528
+ "fingerprint": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
529
+ "reason": "Accepted until the upstream package layout is corrected.",
530
+ "expiresAt": "2026-07-31"
531
+ }
532
+ ],
533
+ "failOnWarnings": true
534
+ }
535
+ ```
536
+
537
+ `ignoreRules` disables every finding with a matching rule ID. Prefer `suppressions` when accepting one specific finding instance: each record requires the exact 64-character lowercase SHA-256 fingerprint shown in Doctor reports, a non-empty review reason, and a real `YYYY-MM-DD` expiration date.
538
+
539
+ Active suppressions remove only the matching finding from the active result and preserve it under `suppressedFindings` for audit output. Expired or invalid records do not suppress findings; Doctor emits `suppression.expired` or `suppression.invalid` warnings instead. Duplicate active records use the first valid match.
540
+
541
+ ### Manage suppressions
542
+
543
+ ```bash
544
+ codex-plugin-doctor suppress add .
545
+ codex-plugin-doctor suppress list .
546
+ codex-plugin-doctor suppress remove .
547
+ ```
548
+
549
+ Interactive add selects one active fingerprinted finding and defaults to an expiration 30 local calendar days from today. The stored `YYYY-MM-DD` record remains active through that UTC calendar date and expires at `00:00 UTC` on the following day. Suppressions match only the exact finding fingerprint; invalid or expired records never hide findings.
550
+
551
+ For automation, supply all add fields or one remove selector and add `--json` when machine-readable output is required:
552
+
553
+ ```bash
554
+ codex-plugin-doctor suppress add . --fingerprint <sha256> --reason "Accepted temporarily." --expires-at 2026-07-31 --json
555
+ codex-plugin-doctor suppress list . --json
556
+ codex-plugin-doctor suppress remove . --index 0 --json
557
+ codex-plugin-doctor suppress remove . --fingerprint <sha256> --json
558
+ ```
559
+
560
+ Run these when you want Codex Plugin Doctor to find plugins from the local Codex installation:
561
+
562
+ ```bash
563
+ codex-plugin-doctor list --installed
564
+ codex-plugin-doctor check --installed
565
+ codex-plugin-doctor check --installed --all-summary
566
+ codex-plugin-doctor check --installed --compat --all-summary
567
+ codex-plugin-doctor check --installed github
568
+ codex-plugin-doctor check --installed github --runtime --no-animations
569
+ codex-plugin-doctor explain plugin.security.hard_coded_secret
570
+ ```
571
+
572
+ ## GitHub Action
573
+
574
+ ```yaml
575
+ name: Validate Codex plugin
576
+
577
+ on:
578
+ pull_request:
579
+
580
+ jobs:
581
+ doctor:
582
+ runs-on: ubuntu-latest
583
+ steps:
584
+ - uses: actions/checkout@v5
585
+ - uses: Esquetta/CodexPluginDoctor@v1.71.0
586
+ with:
587
+ version: "1.71.0"
588
+ path: .
589
+ runtime: "true"
590
+ policy: codex-publish
591
+ corpus: "true"
592
+ contract: "true"
593
+ upload-artifact: "true"
594
+ artifact-name: codex-plugin-doctor-reports
595
+ review-bundle: "true"
596
+ review-bundle-verify: "true"
597
+ ```
598
+
599
+ The action writes `codex-plugin-doctor-summary.md`, `codex-plugin-doctor-report.json`, `codex-plugin-doctor-action-manifest.json`, optional `codex-plugin-doctor.sarif`, optional validation corpus and quality metrics reports, optional `output-contract.json`, and optional signed `review-bundle/` files to `codex-plugin-doctor-reports`, appends the Markdown report to the GitHub Actions step summary, uploads the report directory as an artifact, and then returns the real validation exit code. Set `submission: "true"` to add offline submission preflight reports; set `require-submission-ready: "true"` only with that opt-in to make automatic blockers fail the job. Review bundle generation requires a signing key environment variable such as `CODEX_PLUGIN_DOCTOR_SIGNING_KEY`. For runtime probing, SARIF output, corpus quality regression gates, corpus and contract artifacts, review bundle artifacts, installed plugin cache checks, CI policy presets, and pinned release examples, see [GitHub Action Usage](./docs/guides/github-action.md).
600
+
601
+ To self-test this repository after cloning it:
602
+
603
+ ```bash
604
+ codex-plugin-doctor check examples/codex-doctor-runtime --runtime --no-animations
605
+ ```
606
+
607
+ ## Repository Layout
608
+
609
+ ```text
610
+ docs/ Public architecture, guides, rules, security, and contributor docs
611
+ examples/ Manual plugin packs for local CLI testing
612
+ src/ CLI, validation logic, runtime probing, reports
613
+ tests/ Fixture-based regression tests
614
+ ```
615
+
616
+ ## Validation Evidence
617
+
618
+ The validator is tuned against local fixtures and real marketplace-style plugin packages. See:
619
+
620
+ - [Real-World Validation Workflow](./docs/guides/real-world-validation.md)
621
+ - [Examples](./examples/README.md)
622
+ - [Rule Catalog](./docs/rules/catalog.md)
623
+ - [Official Plugin Components](./docs/architecture/official-plugin-components.md)
624
+
625
+ Recent validation waves covered:
626
+
627
+ - curated Codex plugin cache packages
628
+ - marketplace-style plugin snapshots
629
+ - YAML block-scalar skill metadata
630
+ - media and visual workflow metadata
631
+
632
+ ## Release Readiness
633
+
634
+ Release preparation is reproducible from the repository:
635
+
636
+ ```bash
637
+ npm run prepare-release
638
+ npm run release-check
639
+ ```
640
+
641
+ `prepare-release` runs tests, builds the TypeScript output, and performs `npm pack --dry-run`. `release-check` adds release preflight checks for a clean git tree, existing npm versions, existing version tags, package/lockfile/changelog version consistency, tests, build, pack dry-run, fresh temp install audit, and publish dry-run.
642
+
643
+ For plugin packages, `codex-plugin-doctor release check .` performs static readiness checks by default. Runtime probing executes package-local MCP servers and therefore requires an explicit `--runtime`; protected workflows can also require the approved runtime-plan digest.
644
+
645
+ Related docs:
646
+
647
+ - [Changelog](./CHANGELOG.md)
648
+ - [Contributing](./CONTRIBUTING.md)
649
+ - [Security Policy](./SECURITY.md)
650
+ - [Code of Conduct](./CODE_OF_CONDUCT.md)
651
+ - [NPM Release Checklist](./docs/contributing/npm-release-checklist.md)
652
+ - [Release Candidate Workflow](./docs/contributing/release-candidates.md)
653
+ - [Versioning and Releases](./docs/contributing/releasing.md)
654
+
655
+ ## Contributing
656
+
657
+ Contributions are welcome once the repository is public. Start with:
658
+
659
+ - [Contributing](./CONTRIBUTING.md)
660
+ - [Security Policy](./SECURITY.md)
661
+ - [Validation tuning issue template](./.github/ISSUE_TEMPLATE/validation_tuning.yml)
662
+
663
+ ## Support
664
+
665
+ If this tool saves you time, GitHub stars and sponsorship help signal that the project is worth continuing.
666
+
667
+ - Star the repository on GitHub.
668
+ - Use GitHub Sponsors through the repository funding link.
669
+ - Open validation tuning issues for false positives or false negatives.
670
+
671
+ ## Product Direction
672
+
673
+ Codex Plugin Doctor starts as a Codex-specific validator and can grow into a broader MCP Doctor over time.
674
+
675
+ The immediate goal is not a marketplace, dashboard, or hosted website. The immediate goal is a trustworthy local preflight check for Codex-compatible plugin bundles.