@geoql/doctor

July 6, 2026 · View on GitHub

Your agent writes bad Vue/Nuxt. This catches it.

npm npm JSR License: MIT dashboard

What is this?

A pnpm monorepo of CLIs, oxlint + eslint plugins, and a language server 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.

Full docs, rule reference, config, and scoring live at docs.the-doctor.report.

Hosted dashboard (optional)

The CLI is the whole product and stays free. If you want the score tracked over time instead of just printed once, the-doctor.report is a hosted dashboard: push a run from CI with --push, and it keeps the score trend, per-rule findings, and per-branch history for each project. It stores rule IDs, severities, and file paths only — never your source, snippets, or messages. Nothing about local CLI usage phones home; the dashboard is opt-in and gated behind your own API key.

Ecosystem

RepoWhatLink
geoql/doctor (this repo)OSS CLIs + oxlint rule pluginsgithub.com/geoql/doctor
geoql/doctor-actionGitHub Action wrappergithub.com/geoql/doctor-action
the-doctor.reportHosted SaaS dashboard (private)app.the-doctor.report
DocsRules, CLI, scoring referencedocs.the-doctor.report

Packages

PackageVersionDescription
@geoql/vue-doctornpmCLI for Vue 3 projects
@geoql/nuxt-doctornpmCLI for Nuxt 4 projects
@geoql/doctor-corenpmAudit engine: scoring, reporters, hybrid two-pass analysis
@geoql/doctor-rule-corenpmLinter-neutral rule cores shared by the oxlint/eslint plugins
@geoql/oxlint-plugin-vue-doctornpmoxlint JS plugin: Vue 3 rules
@geoql/oxlint-plugin-nuxt-doctornpmoxlint JS plugin: Nuxt 4 rules
@geoql/eslint-plugin-vue-doctornpmESLint flat-config plugin: Vue 3 rules
@geoql/eslint-plugin-nuxt-doctornpmESLint flat-config plugin: Nuxt 4 rules
@geoql/doctor-language-servernpmLSP server for editor integration (npm-only)

The two CLIs ship at 1.2.2. All nine packages publish to npm with OIDC provenance; the eight library/plugin packages also publish to JSR (the language server is npm-only — it is a stdio binary run via npx, with npm-only vscode-* deps).

Quick start

# Audit a Vue 3 project (npm)
npx -y @geoql/vue-doctor

# Audit a Nuxt 4 project (npm)
npx -y @geoql/nuxt-doctor

# Run from JSR (Deno)
deno run -A jsr:@geoql/vue-doctor
deno run -A jsr:@geoql/nuxt-doctor

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.

Monorepo layout

geoql/doctor/
├── packages/
│   ├── doctor-core/                  # @geoql/doctor-core — audit engine
│   ├── doctor-rule-core/             # @geoql/doctor-rule-core — shared rule cores
│   ├── vue-doctor/                   # @geoql/vue-doctor — Vue 3 CLI
│   ├── nuxt-doctor/                  # @geoql/nuxt-doctor — Nuxt 4 CLI
│   ├── oxlint-plugin-vue-doctor/     # Vue 3 oxlint rules
│   ├── oxlint-plugin-nuxt-doctor/    # Nuxt 4 oxlint rules
│   ├── eslint-plugin-vue-doctor/     # Vue 3 eslint rules
│   ├── eslint-plugin-nuxt-doctor/    # Nuxt 4 eslint rules
│   ├── doctor-language-server/       # LSP server (npm-only)
│   ├── vscode-doctor/                # VS Code extension (not published to npm)
│   └── benchmark/                    # perf workspace (not published)
├── apps/docs/                        # docs.the-doctor.report (Nuxt)
└── docs/SPEC.md                      # the locked spec

CLI flags

Both vue-doctor and nuxt-doctor share the same surface. Key flags:

FlagPurpose
--preset <name>Base preset: minimal | recommended | strict | all
--format <kind>agent (default) | pretty | json | json-compact | sarif | html | pr-comment
--fail-on <level>Exit non-zero on error | warn | none (default error)
--threshold <n>Minimum passing score 0-100
--rule <id:level>Override one rule (repeatable), e.g. --rule a/b:off
--fixAuto-fix oxlint-pass findings in place (full scan only)
--diff / --staged / --fullScope to changed, staged, or all files
--category <cat> / --dimension <dim>Score only rules in a category or dimension (repeatable)
--max-duration <seconds>Soft time budget; on timeout, return partial results (incomplete + skippedCheckReasons)
--scorePrint only the integer score
--output <file>Write the report to a file
--pr-commentEmit a Markdown PR-comment body
--pushPOST privacy-stripped findings to the SaaS (needs --api-key)
--push-url <url>Findings endpoint (default https://app.the-doctor.report/api/v1/findings)
--api-key <key>the-doctor.report API key (doc_…), sent as the x-api-key header
--push-project <slug>Dashboard project slug, e.g. owner/repo (defaults to the audited dir name)

Subcommands: list-rules, explain <ruleId>, inspect [dir], init [dir], ci install [dir] (scaffold a CI workflow that runs geoql/doctor-action@v2). Run vue-doctor --help for the complete list. The JSON report's projectInfo.frameworkDetected boolean tells a real Vue/Nuxt audit apart from a scan that found no project.

Scoring model

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.

Development

pnpm install
pnpm run lint        # vp lint
pnpm run format      # vp fmt
pnpm run build       # vp pack per package
pnpm run coverage    # vitest run --coverage (100% gate)

Requires Node >=24.11.0 and pnpm 11.8.0.

License

MIT © Vinayak Kulkarni