|
2 | 2 |
|
3 | 3 | > Your agent writes bad Vue/Nuxt. This catches it. |
4 | 4 |
|
5 | | -A pair of CLIs and oxlint plugins that audit Vue 3 + Nuxt 4 apps for performance, correctness, security, and AI-agent anti-patterns. It does not scaffold or generate — it _critiques_ the code your agent just wrote and gives it a deterministic health score. |
| 5 | +[](https://www.npmjs.com/package/@geoql/vue-doctor) |
| 6 | +[](https://www.npmjs.com/package/@geoql/nuxt-doctor) |
| 7 | +[](https://jsr.io/@geoql/vue-doctor) |
| 8 | +[](./LICENSE) |
6 | 9 |
|
7 | | -**Documentation:** [docs.the-doctor.report](https://docs.the-doctor.report) |
| 10 | +## What is this? |
| 11 | + |
| 12 | +A pnpm monorepo of CLIs and oxlint plugins that audit Vue 3 and Nuxt 4 apps for performance, correctness, security, and AI-agent anti-patterns. It does not scaffold or generate. It critiques the code your agent just wrote and gives it a deterministic 0-100 health score. The audit runs fully local and offline: same code in, same score out. |
| 13 | + |
| 14 | +Full docs, rule reference, config, and scoring live at [docs.the-doctor.report](https://docs.the-doctor.report). |
| 15 | + |
| 16 | +## Ecosystem |
| 17 | + |
| 18 | +| Repo | What | Link | |
| 19 | +| -------------------------- | ------------------------------- | ------------------------------------------------------------------------ | |
| 20 | +| `geoql/doctor` (this repo) | OSS CLIs + oxlint rule plugins | [github.com/geoql/doctor](https://github.com/geoql/doctor) | |
| 21 | +| `geoql/doctor-action` | GitHub Action wrapper | [github.com/geoql/doctor-action](https://github.com/geoql/doctor-action) | |
| 22 | +| `the-doctor.report` | Hosted SaaS dashboard (private) | [app.the-doctor.report](https://app.the-doctor.report) | |
| 23 | +| Docs | Rules, CLI, scoring reference | [docs.the-doctor.report](https://docs.the-doctor.report) | |
8 | 24 |
|
9 | 25 | ## Packages |
10 | 26 |
|
11 | | -| Package | Description | Version | |
12 | | -| ------------------------------------------------------------------------ | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | |
13 | | -| [`@geoql/doctor-core`](packages/doctor-core) | Audit engine, scoring, reporters | [](https://www.npmjs.com/package/@geoql/doctor-core) | |
14 | | -| [`@geoql/oxlint-plugin-vue-doctor`](packages/oxlint-plugin-vue-doctor) | oxlint JS plugin: Vue 3 rules | [](https://www.npmjs.com/package/@geoql/oxlint-plugin-vue-doctor) | |
15 | | -| [`@geoql/oxlint-plugin-nuxt-doctor`](packages/oxlint-plugin-nuxt-doctor) | oxlint JS plugin: Nuxt 4 rules | [](https://www.npmjs.com/package/@geoql/oxlint-plugin-nuxt-doctor) | |
16 | | -| [`@geoql/vue-doctor`](packages/vue-doctor) | CLI: `npx -y @geoql/vue-doctor` | [](https://www.npmjs.com/package/@geoql/vue-doctor) | |
17 | | -| [`@geoql/nuxt-doctor`](packages/nuxt-doctor) | CLI: `npx -y @geoql/nuxt-doctor` | [](https://www.npmjs.com/package/@geoql/nuxt-doctor) | |
| 27 | +| Package | Version | Description | |
| 28 | +| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | |
| 29 | +| [`@geoql/doctor-core`](packages/doctor-core) | [](https://www.npmjs.com/package/@geoql/doctor-core) | Audit engine: scoring, reporters, hybrid two-pass analysis | |
| 30 | +| [`@geoql/vue-doctor`](packages/vue-doctor) | [](https://www.npmjs.com/package/@geoql/vue-doctor) | CLI for Vue 3 projects | |
| 31 | +| [`@geoql/nuxt-doctor`](packages/nuxt-doctor) | [](https://www.npmjs.com/package/@geoql/nuxt-doctor) | CLI for Nuxt 4 projects | |
| 32 | +| [`@geoql/oxlint-plugin-vue-doctor`](packages/oxlint-plugin-vue-doctor) | [](https://www.npmjs.com/package/@geoql/oxlint-plugin-vue-doctor) | oxlint JS plugin: Vue 3 rules | |
| 33 | +| [`@geoql/oxlint-plugin-nuxt-doctor`](packages/oxlint-plugin-nuxt-doctor) | [](https://www.npmjs.com/package/@geoql/oxlint-plugin-nuxt-doctor) | oxlint JS plugin: Nuxt 4 rules | |
| 34 | + |
| 35 | +The two CLIs ship at `1.1.1`, published on [npm](https://www.npmjs.com/org/geoql) and [JSR](https://jsr.io/@geoql) with OIDC provenance. |
18 | 36 |
|
19 | 37 | ## Quick start |
20 | 38 |
|
21 | 39 | ```sh |
22 | | -# Audit a Vue 3 project |
| 40 | +# Audit a Vue 3 project (npm) |
23 | 41 | npx -y @geoql/vue-doctor |
24 | 42 |
|
25 | | -# Audit a Nuxt 4 project |
| 43 | +# Audit a Nuxt 4 project (npm) |
26 | 44 | npx -y @geoql/nuxt-doctor |
| 45 | + |
| 46 | +# Run from JSR (Deno) |
| 47 | +deno run -A jsr:@geoql/vue-doctor |
| 48 | +deno run -A jsr:@geoql/nuxt-doctor |
27 | 49 | ``` |
28 | 50 |
|
29 | | -## Documentation |
| 51 | +Both CLIs print a health score with grouped diagnostics and exit non-zero when findings breach your `--fail-on` threshold, so they drop straight into CI. |
| 52 | + |
| 53 | +## Monorepo layout |
| 54 | + |
| 55 | +``` |
| 56 | +geoql/doctor/ |
| 57 | +├── packages/ |
| 58 | +│ ├── doctor-core/ # @geoql/doctor-core — audit engine |
| 59 | +│ ├── vue-doctor/ # @geoql/vue-doctor — Vue 3 CLI |
| 60 | +│ ├── nuxt-doctor/ # @geoql/nuxt-doctor — Nuxt 4 CLI |
| 61 | +│ ├── oxlint-plugin-vue-doctor/ # Vue 3 oxlint rules |
| 62 | +│ ├── oxlint-plugin-nuxt-doctor/ # Nuxt 4 oxlint rules |
| 63 | +│ └── benchmark/ # perf workspace (not published) |
| 64 | +├── apps/docs/ # docs.the-doctor.report (Nuxt) |
| 65 | +└── docs/SPEC.md # the locked spec |
| 66 | +``` |
| 67 | + |
| 68 | +## CLI flags |
| 69 | + |
| 70 | +Both `vue-doctor` and `nuxt-doctor` share the same surface. Key flags: |
30 | 71 |
|
31 | | -Full docs — rules, CLI reference, config, and scoring — live at **[docs.the-doctor.report](https://docs.the-doctor.report)**. |
| 72 | +| Flag | Purpose | |
| 73 | +| -------------------------------- | ---------------------------------------------------------------------------------------------- | |
| 74 | +| `--preset <name>` | Base preset: `minimal` \| `recommended` \| `strict` \| `all` | |
| 75 | +| `--format <kind>` | `agent` (default) \| `pretty` \| `json` \| `json-compact` \| `sarif` \| `html` \| `pr-comment` | |
| 76 | +| `--fail-on <level>` | Exit non-zero on `error` \| `warn` \| `none` (default `error`) | |
| 77 | +| `--threshold <n>` | Minimum passing score 0-100 | |
| 78 | +| `--rule <id:level>` | Override one rule (repeatable), e.g. `--rule a/b:off` | |
| 79 | +| `--fix` | Auto-fix oxlint-pass findings in place (full scan only) | |
| 80 | +| `--diff` / `--staged` / `--full` | Scope to changed, staged, or all files | |
| 81 | +| `--score` | Print only the integer score | |
| 82 | +| `--output <file>` | Write the report to a file | |
| 83 | +| `--pr-comment` | Emit a Markdown PR-comment body | |
| 84 | +| `--push` | POST privacy-stripped findings to the SaaS (needs `--api-key`) | |
| 85 | +| `--push-url <url>` | Findings endpoint (default `https://app.the-doctor.report/api/v1/findings`) | |
| 86 | +| `--api-key <key>` | the-doctor.report API key (`doc_…`), sent as the `x-api-key` header | |
| 87 | +| `--push-project <slug>` | Dashboard project slug, e.g. `owner/repo` (defaults to the audited dir name) | |
32 | 88 |
|
33 | | -Both CLIs run a deterministic audit, print a health score (0–100) with grouped |
34 | | -diagnostics, and exit non-zero when findings breach your `--fail-on` threshold — |
35 | | -so they drop straight into CI. See the [docs](https://docs.the-doctor.report) |
36 | | -for flags (`--fix`, `--ci`, `--sarif`, `--json`, presets) and the full rule set. |
| 89 | +Subcommands: `list-rules`, `explain <ruleId>`, `inspect [dir]`, `init [dir]`. Run `vue-doctor --help` for the complete list. |
37 | 90 |
|
38 | | -## Status |
| 91 | +## Scoring model |
39 | 92 |
|
40 | | -`v0.1.0` — published on [npm](https://www.npmjs.com/org/geoql) and [JSR](https://jsr.io/@geoql) with provenance. See the [v1.0 milestone](https://github.com/geoql/doctor/milestone/3) for the roadmap. |
| 93 | +Internal severities are `error`, `warn`, and `info` with weights `5`, `2`, and `0.5`. The score uses square-root decay: each repeated occurrence of a rule contributes `weight × 1/√(i+1)`, so the first hit costs full weight and repeats cost less. The final score is `max(0, round(100 − penalty))`. `--fail-on` accepts `error`, `warn`, or `none`. An invalid value exits `2`. |
41 | 94 |
|
42 | 95 | ## Development |
43 | 96 |
|
44 | 97 | ```sh |
45 | 98 | pnpm install |
46 | | -pnpm run lint |
47 | | -pnpm run format |
| 99 | +pnpm run lint # vp lint |
| 100 | +pnpm run format # vp fmt |
| 101 | +pnpm run build # vp pack per package |
| 102 | +pnpm run coverage # vitest run --coverage (100% gate) |
48 | 103 | ``` |
49 | 104 |
|
50 | 105 | Requires Node `>=24` and pnpm `11.4.0`. |
|
0 commit comments