Thanks to visit codestin.com
Credit goes to lib.rs

#linter #typescript #convex #static-analysis

bin+lib convex-doctor

Diagnose your Convex backend for anti-patterns, security issues, and performance problems

2 unstable releases

0.2.0 Feb 24, 2026
0.1.0 Feb 24, 2026

#7 in #convex

MIT license

310KB
4.5K SLoC

convex-doctor

convex-doctor CLI output

Diagnose your Convex backend for anti-patterns, security issues, and performance problems.

convex-doctor is a static analysis CLI for Convex projects. It parses your convex/ directory, runs 65 rules across 7 categories, and produces a weighted 0-100 health score. Think of it as ESLint, but purpose-built for Convex backends.

Benchmarks

Tested against 18 open-source Convex applications

Project Stars Score Errors Warnings Info Total
google-docs 73 94/100 0 15 2 17
Ai-Website-Builder 122 92/100 0 15 1 16
miro-clone 82 89/100 3 18 13 34
replicate 197 88/100 3 15 0 18
livecanvas 192 84/100 3 31 0 34
quizzex 1 83/100 3 65 4 72
podcastr 782 77/100 12 63 6 81
convex-saas 338 76/100 5 51 26 82
convjobs 2 76/100 6 58 4 68
BloxAI 91 76/100 9 81 0 90
notion-clone 141 76/100 10 38 28 76
react-starter-kit 615 69/100 12 39 4 55
ticket-marketplace 210 64/100 22 131 20 173
OpenChat 138 56/100 49 188 15 252
travel-planner-ai 241 55/100 28 173 9 210
youpac-ai 315 55/100 50 192 120 362
opensync 301 48/100 70 277 58 405
markdown-site 547 36/100 77 316 48 441

Benchmarks run on Feb 24, 2026 against each project's main branch. Sorted by score.

Installation

Grab the latest release for your platform from GitHub Releases:

# macOS (Apple Silicon)
curl -L https://github.com/nooesc/convex-doctor/releases/latest/download/convex-doctor-aarch64-darwin -o convex-doctor
chmod +x convex-doctor && sudo mv convex-doctor /usr/local/bin/

# macOS (Intel)
curl -L https://github.com/nooesc/convex-doctor/releases/latest/download/convex-doctor-x86_64-darwin -o convex-doctor
chmod +x convex-doctor && sudo mv convex-doctor /usr/local/bin/

# Linux (x86_64)
curl -L https://github.com/nooesc/convex-doctor/releases/latest/download/convex-doctor-x86_64-linux -o convex-doctor
chmod +x convex-doctor && sudo mv convex-doctor /usr/local/bin/

# Linux (aarch64)
curl -L https://github.com/nooesc/convex-doctor/releases/latest/download/convex-doctor-aarch64-linux -o convex-doctor
chmod +x convex-doctor && sudo mv convex-doctor /usr/local/bin/

Install from crates.io

cargo install convex-doctor

Build from source

git clone https://github.com/nooesc/convex-doctor.git
cd convex-doctor
cargo build --release
# Binary is at ./target/release/convex-doctor

Usage

Run from your project root (the directory containing convex/):

# Basic scan
convex-doctor

# Verbose output with file paths and line numbers
convex-doctor -v

# JSON output (for CI or tooling)
convex-doctor --format json

# Score only (prints just the number, e.g. "87")
convex-doctor --score

# Diff mode: only analyze files changed vs a base branch
convex-doctor --diff main
# Note: diff mode only runs file-level rules on changed files.

# Scan a specific project path
convex-doctor /path/to/my-project

Rules

convex-doctor runs 65 rules organized into 7 categories. Each category carries a different weight in the final score.

Category Weight Rules Description
Security 1.5x 13 Arg/return validators, auth checks, internal API misuse, secrets, CORS, access control, generic args
Performance 1.2x 12 Unbounded collect, missing indexes, Date.now() in queries, loop mutations, N+1 patterns, pagination
Correctness 1.5x 15 Unwaited promises, deprecated APIs, side effects in queries, scheduler issues, non-determinism
Schema 1.0x 8 Missing schema, deep nesting, redundant indexes, search index filters, optional field handling
Architecture 0.8x 8 Large handlers, monolithic files, function chains, mixed types, missing helpers
Configuration 1.0x 5 Missing convex.json, auth config, generated code, tsconfig, node version
Client-Side 1.0x 4 Mutation in render, unhandled loading states, missing ConvexProvider

Rule reference

Security (13 rules)
Rule ID Severity What it detects
security/missing-arg-validators error Public functions without args validators
security/missing-return-validators warning Functions without returns validators
security/missing-auth-check warning Public functions that never call ctx.auth.getUserIdentity()
security/internal-api-misuse error Server-to-server calls using api.* instead of internal.*
security/hardcoded-secrets error API keys, tokens, or secrets hardcoded in source
security/env-not-gitignored error .env.local exists but is not in .gitignore
security/spoofable-access-control warning Access control trusting spoofable client args (e.g. userId, role)
security/missing-table-id warning Using string IDs instead of v.id("table") for document references
security/missing-http-auth error HTTP action endpoints without authentication checks
security/conditional-function-export warning Convex functions conditionally exported based on environment
security/generic-mutation-args warning Public mutations using v.any() in argument validators
security/overly-broad-patch warning ctx.db.patch with spread args that bypass validation
security/http-missing-cors warning HTTP routes without CORS headers
Performance (12 rules)
Rule ID Severity What it detects
perf/unbounded-collect error .collect() without .take(n) limit
perf/filter-without-index warning .filter() calls that scan entire tables
perf/date-now-in-query error Date.now() in query functions (breaks caching)
perf/loop-run-mutation error ctx.runMutation/ctx.runQuery inside loops (N+1)
perf/sequential-run-calls warning Multiple sequential ctx.run* calls in an action
perf/unnecessary-run-action warning ctx.runAction called from within an action
perf/helper-vs-run warning ctx.runQuery/ctx.runMutation inside a query or mutation
perf/missing-index-on-foreign-key warning v.id("table") field in schema without a corresponding index
perf/action-from-client warning Client calling actions directly instead of mutations
perf/collect-then-filter warning .collect() followed by JS .filter() instead of using DB query filters
perf/large-document-write warning Inserting documents with 20+ fields in a single write
perf/no-pagination-for-list warning Public query with .collect() returning unbounded results to client
Correctness (15 rules)
Rule ID Severity What it detects
correctness/unwaited-promise error ctx.db.insert, ctx.runMutation, etc. without await
correctness/old-function-syntax warning Legacy function registration syntax
correctness/db-in-action error Direct ctx.db.* calls inside actions
correctness/deprecated-api warning Usage of deprecated Convex APIs (v.bigint(), v.bytes())
correctness/wrong-runtime-import warning Incompatible runtime imports (Node in edge, browser in server)
correctness/direct-function-ref warning Direct function refs passed to ctx.run* instead of api.*/internal.*
correctness/missing-unique warning .first() on indexed query where .unique() may be appropriate
correctness/query-side-effect error Side effects (ctx.db.insert/patch/delete) inside query functions
correctness/mutation-in-query error ctx.runMutation called from within a query function
correctness/cron-uses-public-api warning Cron jobs referencing public api.* instead of internal.*
correctness/node-query-mutation warning Queries/mutations using "use node" runtime unnecessarily
correctness/scheduler-return-ignored info ctx.scheduler.runAfter return value not captured
correctness/non-deterministic-in-query warning Math.random(), new Date(), crypto in query functions
correctness/replace-vs-patch info ctx.db.replace used where ctx.db.patch may be safer
correctness/generated-code-modified warning Generated files (_generated/) appear to be manually modified
Schema (8 rules)
Rule ID Severity What it detects
schema/missing-schema warning No schema.ts file found in convex/ directory
schema/deep-nesting warning Schema validators nested more than 3 levels deep
schema/array-relationships warning v.array(v.id(...)) patterns that may grow unbounded
schema/redundant-index warning Index that is a prefix of another index on the same table
schema/too-many-indexes info Table with 8+ indexes (limit is 32)
schema/missing-search-index-filter info Search index without filterFields
schema/optional-field-no-default-handling warning 5+ optional schema fields without undefined handling
schema/missing-index-for-query warning Query filters on a field with no matching index
Architecture (8 rules)
Rule ID Severity What it detects
arch/large-handler warning Handler functions exceeding 50 lines
arch/monolithic-file warning Files with more than 10 exported functions
arch/duplicated-auth warning 3+ functions with inline auth checks in the same file
arch/action-without-scheduling info Actions that could use ctx.scheduler instead of direct calls
arch/no-convex-error info throw new Error(...) instead of throw new ConvexError(...)
arch/mixed-function-types info File mixing public and internal function exports
arch/no-helper-functions info Multiple large handlers with no shared helper functions
arch/deep-function-chain warning Action with 5+ ctx.run* calls forming a deep chain
Configuration (5 rules)
Rule ID Severity What it detects
config/missing-convex-json warning No convex.json found in project root
config/missing-auth-config error Functions use ctx.auth but no auth.config.ts exists
config/missing-generated-code warning No _generated/ directory found
config/outdated-node-version warning Node version in config is outdated
config/missing-tsconfig info No tsconfig.json found in convex directory
Client-Side (4 rules)
Rule ID Severity What it detects
client/mutation-in-render error useMutation called in React render body (infinite loop)
client/unhandled-loading-state warning useQuery result used without checking for undefined loading state
client/action-instead-of-mutation info useAction used where useMutation may suffice
client/missing-convex-provider info Convex hooks used without ConvexProvider in component tree

Scoring

The health score ranges from 0 to 100. Each finding deducts points based on its severity and category weight, with per-rule caps to prevent a single noisy rule from dominating the score.

Score Label Meaning
85 - 100 Healthy Few or no issues detected
70 - 84 Needs attention Some issues worth addressing
50 - 69 Unhealthy Significant problems found
0 - 49 Critical Serious issues requiring immediate attention

Configuration

Create a convex-doctor.toml in your project root to customize behavior:

# Disable specific rules
[rules]
"security/missing-return-validators" = "off"
"arch/monolithic-file" = "off"

# Ignore files by glob pattern
[ignore]
files = [
  "convex/_generated/**",
  "convex/testHelpers.ts",
]

# CI: exit with code 1 if score is below threshold
[ci]
fail_below = 70

CI integration

GitHub Actions

Add convex-doctor to your CI pipeline using the prebuilt binary (runs in ~2 seconds, no Rust toolchain needed):

name: Convex Health Check
on: [pull_request]

jobs:
  convex-doctor:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install convex-doctor
        run: |
          curl -L https://github.com/nooesc/convex-doctor/releases/latest/download/convex-doctor-x86_64-linux -o convex-doctor
          chmod +x convex-doctor

      - name: Run convex-doctor
        run: ./convex-doctor

By default, convex-doctor exits with code 0. To fail the build when the score drops below a threshold, add a convex-doctor.toml to your project root:

[ci]
fail_below = 70

convex-doctor will exit with code 1 when the score is below fail_below.

Diff mode (PR-only scanning)

Only lint files changed in the pull request — useful for large codebases:

      - name: Run convex-doctor (changed files only)
        run: ./convex-doctor --diff origin/main

Alternative: install via cargo

If you prefer using the Rust toolchain:

      - uses: dtolnay/rust-toolchain@stable
      - run: cargo install convex-doctor
      - run: convex-doctor

Note: cargo install takes ~30s to compile. The prebuilt binary approach is faster.

License

MIT

Dependencies

~17MB
~303K SLoC